VegetaY
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

一、类
类是对某一类事物的抽象的,类似共同点的抽象描述。对象是类中具体的个体。
1、定义类
[修饰符] class 类名 [extends 父类名] [implements 接口名]{ //定义类
[修饰符] 数据类型 变量名 [=值]; //声明成员变量
[修饰符] [返回值类型] 方法名 ([参数]) { //声明成员方法
[return 返回值] //返回类型为viod 可以省略不写。
}
}
//修饰符(访问控制符):
//private:当前类可以访问
//default:当前包可以访问
//protected:当前类、包、以及其他包内的子类
//public:所有,也是默认修饰符
2、创建对象
类名 对象名 = new 类名();
/* Person p = new Person();
将Person()在内存中的地址赋值给Person类型的变量p
Person类存放于堆内存,p存放于栈内存。
栈内存:存放基本数据类型变量、对象的引用变量。
堆内存:存放new创建的对象和数组。
*/
3、使用对象
对象引用.对象成员
or
new 类名().对象成员 //由于没有对象引用,完成访问之后就变成垃圾对象。
二、封装
将对象的状态信息隐藏在对象内部不允许外部直接访问,而是通过该类提供的方法来访问。
具体实施:
属性私有化,使用private修饰。
提供访问的方法。
三、方法重载和递归
1、重载:
定义多个方法名相同,参数不同的方法。
2、递归:
在有结束条件的情况下在方法内部调用自身。
四、构造方法
1、定义:
[修饰符] 类名 ([参数]){
}
// 方法名要和类名相同
// 没有返回值类型声明
// 无返回值,但是可以使用return作为方法结束。
2、构造方法重载:
每个类都至少有一个构造方法,即便没有显式的定义,系统也会自动为类创建一个默认的无参构造方法,默认的无参构造方法什么也不做。如果为类定义了构造方法系统就不提供默认的,也就无法访问。
3、构造方法不可以使用private修饰。
五、this关键字
this指代当前对象,类似python的self
可以使用this在类中调用成员变量、成员方法。
this.成员变量名
this.成员方法名()
this([参数]) //调用构造方法。只能在构造方法只用this调用其他构造方法,必须在构造方法第一行,只能出现一次,不能在一个类中的构造方法互相调用。
六、static关键字
定义一个类时没有具体数据,只有new了实例对象之后才会分配内存。
static修饰的数据在内存中只有一次,能被一个类的所有实例对象共享,不需要new就可以访问,不创建对象。
1、静态变量 !只能修饰成员变量
// 定义
static 数据类型 变量名 [=值];
// 使用
类名.变量名
2、静态方法
// 定义
[修饰符] static 方法名 ([参数]){
}
// 使用
类名.方法名()
/*静态方法内部只能访问类中被static修饰的成员,因为没有static修饰的成员需要创建对象。*/
3、静态代码块
static {
}
/*类被加载时(实例化)执行,类只加载一次,也就只执行一次,通常用于初始化成员*/
七、继承
类的继承指在一个现有类的基础上去构建一个新的类,构建出的子类会自动拥有父类(也叫基类)所有可继承的属性和方法。
语法:
[修饰符] class 子类名 extends 父类名 {
}
// 1、子类继承父类之后就有了父类的所有公共成员
// 2、一个类只能有一个父类
1、重写父类方法
子类中重写父类方法需要和父类被重写的方法具有相同的方法名,参数列表,返回值类型。
子类重写父类方法时不能使用比父类中被重写方法更严格的访问权限。
2、super关键字
用于访问父类成员,包括被重写的方法。当子类重写父类方法时子类对象无法直接访问父类被重写的方法。
语法:
//调用父类的成员变量和成员方法
super.成员变量
super.成员方法([参数])
//调用父类构造方法
super([参数])
!!!使用super调用父类构造方法必须写在子类构造方法的第一行,并且只能写一次!!!
如果在子类构造方法中没有使用super指定调用父类的哪一个构造方法,那么在实例化子类时会默认调用父类无参构造方法。如果父类没有无参构造方法就会报错!
3、Object类
Object类时所有类的父类,每个类都直接或间接继承它。因此被称为超类、基类或者根类。在定义一个类时如果没有用extends指定父类,那么该类会默认继承Object类。
八、final关键字
final用来修饰类、变量、方法,被它修饰后就不可改变。
final修饰的类不能被继承
final class 类名{
[修饰符] final [返回值类型] 方法名(){
}
}
final修饰的方法不能被子类重写
final修饰的变量是常量,只能赋值一次。
九、抽象类和接口
1、抽象类
定义一个类时需要定义一些方法来描述该类的行为和特征,但有些时候这些方法的实现形式是不确定的。针对这一的情况可以使用抽象方法。
抽象方法:
使用abstract修饰,不需要实现方法体。一个类包含了抽象方法那么这个类也必须要用abstract修饰成为抽象类。也就是说含有抽象方法的类就是抽象类。抽象类中也可以有其他类型的方法,所有抽象类也可以没有抽象方法。
语法:
//定义抽象类
[修饰符] abstract class 类名{
//定义抽象方法
[修饰符] abstract [返回值类型] 方法名 ([参数]);
}
抽象类的调用:
抽象类的调用与普通类不同,因为抽象类中可能含有抽象方法,抽象方法没有方法体不能被调用所有抽象类不能实例化。想使用抽象类必须创建一个子类继承抽象类并重写抽象方法。
2、接口
接口是特殊的抽象类,接口中不包含普通方法,内部所有方法都是抽象方法。从JDK8起接口还支持默认方法和静态方法,这两种方法都支持方法体。
定义接口:
[修饰符] interface 接口名 [extends 父接口...] {
[修饰符] [static] [final] 常量类型 常量名 = 常量值;
[public] [abstract] 返回值类型 方法名([参数]);
/*定义默认方法*/
[public] default 返回值类型 方法名([参数]){
//方法体
}
/*定义静态方法*/
[public] static 返回值类型 方法名([参数]){
//方法体
}
}
接口内部可以多个常量和抽象方法。
接口内定义常量必须初始化赋值。
默认方法和静态方法可以有方法体。
实现接口:
[修饰符] class [extends 父类名] [implements 接口......]{
}
接口内静态方法用 "接口名.静态方法名" 调用。
抽象方法和默认方法只能通过接口实现类的实例对象调用。
接口实现类可以在继承另一个类的同时实现多个接口。
接口的实现类必须实现接口中所有!!!抽象方法!!!
接口之间可以使用extends继承。
十、多态
多态是指不同类的对象调用同一个方法时呈现的不同行为。在一个类中定义的属性和方法被其他类继承和重写之后,再把子类对象直接赋值给父类引用变量时,相同的引用类型的变量调用同一个方法将呈现不同的形态。
例子:
/*
多态---由继承,方法重写,父类引用指向子类对象体现。
*/
public class Test { //主类
public static void main(String[] args) {
/*父类引用指向子类对象*/
Animal d = new Dog();
Animal c = new Cat();
d.shout();
c.shout();
}
}
class Animal{ //父类
public void shout() {
System.out.println("Father Class : Animal {Method : shout }");
}
}
class Dog extends Animal{ //子类dog
public void shout() {
System.out.println("Dog : wang!");
}
}
class Cat extends Animal{ //子类cat
public void shout() {
System.out.println("Cat : miao!");
}
}
1、对象的类型转换
在测试类中这种把子类对象赋值给父类引用类型的情况叫做向上转型。在这种情况下无法使用被赋值的父类引用变量去调用子类独有的方法,也就是说只能调用父类和子类共有,就是子类重写过的方法。因为这个父类引用类型变量指向的时父类,所以不能使用父类中没有的方法,即便子类中有也不行。
例子:
public class Test {
public static void main(String[] args) {
Animal d = new Dog();
Animal c = new Cat();
d.shout();
d.eatBaba();/*!!!!!这里调用了Animal没有的方法会报错!!!!!!*/
c.shout(); }
}
class Animal{
public void shout() {
System.out.println("Father Class : Animal {Method : shout }");}
}
class Dog extends Animal{
public void shout() {
System.out.println("Dog : wang!");}
public void eatBaba() {
System.out.println("~~~~");}
}
class Cat extends Animal{
public void shout() {
System.out.println("Cat : miao!");}
}
为了避免以上这种情况我们可以使用强制类型转换把父类引用类型变量转换成子类引用类型赋值给另一个变量使用,这波操作就是向下转型
public class Test {
public static void main(String[] args) {
Animal d = new Dog();
Animal c = new Cat();
d.shout();
Dog niubiDog = (Dog) d; /*这里使用强制类型转换用d创建了一个新的Dog变量*/
niubiDog.eatBaba(); //此时可以调用dog独有的方法
c.shout(); }
}
class Animal{
public void shout() {
System.out.println("Father Class : Animal {Method : shout }");}
}
class Dog extends Animal{
public void shout() {
System.out.println("Dog : wang!");}
public void eatBaba() {
System.out.println("~~~~");}
}
class Cat extends Animal{
public void shout() {
System.out.println("Cat : miao!");}
}
插播一个关键字instanceof,可以判断一个对象是否是某个类或接口的实例或者子类实例。
对象 instanceof 类(或者接口)
十一、内部类
java允许在类的内部定义类,这样的类叫做内部类,这个内部类所在的类称作外部类。
内部类有四种:
1、成员内部类
成员内部类和所在外部类可以互通所有的成员。
定义:
[修饰符] class 类名 [extends 父类名] [implements 接口名]{ //定义类
[修饰符] class 类名 [extends 父类名] [implements 接口名]{
}
}
调用:
外部类名.内部类名 变量名 = new 外部类名().new 内部类名(); //通过创建内部类对象调用
2、局部内部类
也叫做方法内部类,和局部变量一样定义在方法内部,有效范围局限于方法内部。
局部内部类可访问外部类所有成员,而局部内部类中的成员只有在包含它的方法中才可以访问。
3、静态内部类
就是使用static修饰的成员内部类。静态内部类只能访问外部类的静态成员。通过外部类访问静态内部类成员可以跳过外部类直接通过内部类访问静态内部类成员。
外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
4、匿名内部类
匿名内部类其实就是没有名称的内部类,在调用含有接口类型参数的方法时,为了简化代码,通常不会创建一个接口的实现类作为该方法的参数传入,可以通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中直接完成方法的实现。
new 实现的接口 {
//匿名内部类实现部分
}
/**********例子**********/
//定义一个接口
interface Animal{
void shout();
}
public class Test {
//定义一个带接口类型参数的方法
public static void animalShout(Animal an) {
an.shout();}
public static void main(String[] args) {
String name = "cat" ;
//这里调用了需要含有接口类型参数的方法animalShout()
animalShout(
//这里直接使用new Animal()的形式传入一个接口类型的内容,没有定义实现类的名称。
new Animal() {
//这里实现了Animal接口的方法
public void shout() {
System.out.println(name+"miao!");}
}
);
}
}
十二、JDK8的Lambda表达式
针对有且只有一个抽象方法的接口实现,以简洁的表达式形式实现接口功能来作为方法参数。
1、Lambda表达式语法
([参数]) -> {表达式主体}
//只有一个参数时可以省略括号
//表达式主体本质上就是接口中抽象方法的实现,如果只有一条语句可以省略{}。
//lambda表达式允许返回值,当只有一条return时可以省略。
/******例子******/
public class Test {
//定义一个带接口类型参数的方法
public static void animalShout(Animal an) {
an.shout();
}
public static void main(String[] args) {
String name = "cat" ;
//这里调用了需要含有接口类型参数的方法animalShout()
animalShout(
//使用Lambda表达式传入
()->{System.out.println(name+" miao!");}
);
}
}
interface Animal{
void shout();
}
2、函数式接口
函数式接口就是有且仅有一个抽象方法的接口,Lambda表达式可以实现匿名内部类的效果就是基于函数式接口实现的。只有保证接口中只且只有一个抽象方法,Lambda表达式才能推导出所实现的方法。
在JDK8中专门引入@FunctionalInterface注解,用于显示的标注一个函数式接口。强制编辑器进行更严格检查,如果不是函数式接口编译时会报错。
3、方法引用和构造器(构造方法)引用
Lambda表达式的主体只有一条语句时,可以使用::来引用其他类成员。
/******Lambda表达式************** | ******对应引用实例******/
([参数])->对象名.普通方法([参数]) 类名::普通方法名()
([参数])->类名.静态方法([参数]) 类名::静态方法名()
([参数])->对象名.实例方法([参数]) 对象名::实例方法名()
([参数])->new.类名([参数]) 类名::new //引用构造方法
调用静态方法
@FunctionalInterface //使用注解强制编辑器检查Calcable是否为函数式接口
interface Calcable{
int calc(int num);
}
class Math{
public static int abs(int num) {
if (num<0){
return -num;
}else{
return num;
}
}
}
public class Test03 {
private static void printabs(int num,Calcable calcable) {
System.out.println(calcable.calc(num));
}
public static void main(String[] args) {
/*这里的Lanbda表达式就是重写的Calcable下的calc方法
等同于把calc方法重写,调用Math类中的静态方法,等同如下代码 :
int calc(int num){
Math.abs(num)
}
*/
printabs(-10, n->Math.abs(n));
printabs(-10, Math::abs);}
}
其他后续补充
十三、异常
java以异常类的形式将大量非正常情况进行封装,通过异常处理机制对程序运行时发生的各种情况进行处理。
java提供了大量的异常类,这些类都继承于java.lang.Throwable类
Throwable
Error
IOError
AWTError
......
Exception
RuntimeException //运行时异常
ArithemticException
ClassCastException
...... //其他都是编译时异常
Error类
错误类时java运行时系统内部错误或资源耗尽错误,一般修改程序本身时无法修复的。
Exception类
异常类是程序本身可以处理的错误情况。
1、异常的类型
编译时异常:
在程序编写时编译器就会对编写的代码进行检查,出现较明显的异常就必须进行异常处理,否则无法通过编译。
运行时异常:
在程序运行时由java虚拟机自动捕获处理,即使没有try......catch捕获或者throws抛出,程序也能通过编译,但是运行时可能报错。
2、try...catch...finally
——异常的处理
try{
//可能发生异常的语句
}catch(Exception或者其他子类 接收异常的变量){ //类似必须像python: except Exception as err
//捕获到异常要运行的语句
}[finally{
//不管有没有异常都执行的语句
}]
例子:
public class TestException {
public static int divide(int x,int y){
try{
int result=x/y;
return result;}
catch (Exception err1){
System.out.println("捕获到异常: "+err1.getMessage());
}
return -1;
}
public static void main(String[] args) {
int result=divide(4,0);
}
}
3、throws
——指明方法可能抛出的异常
java允许先将异常从当前方法抛出,让后续调用者在使用时再处理。
[修饰符] 返回值类型 方法名([参数]) throws 异常类{
}
例子:
public class TestException {
public static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
public static void main(String[] args) {
int result=divide(4,0);
}
}
//IDEA报错: java: 未报告的异常错误java.lang.Exception; 必须对其进行捕获或声明以便抛出
4、throw
——抛出异常类对象
如果抛出的时Error或者RuntimeException或其他子类异常对象,则无需thows或者try对异常进行处理。
[修饰符] 返回值类型 方法名([参数]) throws 异常类{
throw new Exception或其子类构造方法; //throw要在方法体中使用。
}
例子:
public class TestException {
public static void divide(int x,int y) throws Exception{
if (y==0){
throw new Exception("y怎么等于0 ? !!!");
}else{
int result = x/y;
System.out.println("x/y = "+result);
}
}
public static void main(String[] args) {
try{
divide(4,0);
}catch (Exception err1){
System.out.println("捕获到异常 : "+err1.getMessage());
}
}
}
5、自定义异常
自定义异常必须继承Exception或其子类。
/*没有特殊要求,自定义异常只需要继承Exception或其子类并在构造方法中调用父类构造方法*/
[修饰符] class 类名 extends Exception或其子类 {
public 类名(){
super();
}
}
例子:
/*异常类的使用*/
public class TestException {
public static void divide(int x,int y) throws MyException{
if (y==0){
throw new MyException("y怎么等于0 ? !!!");
}else{
int result = x/y;
System.out.println("x/y = "+result);
}
}
public static void main(String[] args) {
try{
divide(4,0);
}catch (Exception err1){
System.out.println("捕获到异常 : "+err1.getMessage());
}
}
}
/*下面时自定义的异常类*/
class MyException extends Exception {
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
十四、垃圾回收
java虚拟机会自动回收垃圾对象占用的内存!
1、对象在内存中的状态
一个对象在内存中运行时根据其被引用变量所引用的状态可以分为三种:
可用:
对象创建之后有一个以上的引用变量引用
可恢复:
没有引用变量引用就进入可恢复状态。垃圾回收机制准备回收内存,在回收之前系统会调用所有可恢复状态对象的finalize()方法进行资源清理,如果在调用finalize()之前有另一个引用变量引用该对象就恢复可用。
不可用:
对象失去所有引用变量的关联,系统已经调用所有的可恢复对象的finalize()方法则进入不可用状态。系统回收内存。
进入不可用状态后也会暂时保存在内存中,只有这样的垃圾堆积到一定程度才会开启垃圾回收释放内存。
2、强制进行垃圾回收
2.1-调用System类的gc()静态方法
System.gc() //这个调用的其实也是Runtime的方法
2.2-调用Runtime对象的gc()实例方法
Runtime.getRuntime().gc()
调用强制回收之后,系统是否会立即进行垃圾回收也是未知数。
当一个对象在内存中被释放的时候,他的finalize()方法被自动调用。finalize()定义在Object中。
protected void finalize() throws Throwable{}
3、补充
程序认为需要更多内存时,垃圾回收才会启动。但有些特殊情况下不可恢复的垃圾对象不会被回收,例如占用内存少,而系统有没有严重的内存需求,就不回收这种小垃圾,finalize()也不会调用。
ps:java小趴菜一个,如有错误还望大佬不吝赐教
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
