final
final可修饰成员变量,局部变量,形参,类,方法
static可修饰属性,方法,类,静态代码块
被final修饰后的标识符叫做常量(常量一般用大写字母表示),且内存地址不能再变了
被final修饰后必须赋初值,且只有一次机会
public final int a = 12;
public final StringBuilder sb = new StringBuilder();
sb.append("zhangaoqi");
sb.append("zaq");
System.out.println(sb.toString());//输出 zhangaoqizaq
上面的sb可以被修改,很神奇,这是因为他改变的不是StringBuilder,而是StringBuilder里的内容
- 静态常量(static final):不创建对象就能访问,且值不能改变
public static final int a = 1;
- 被final修饰的方法在继承时不能再被重写
public static fianl void foo() {
System.out.println("a");
}
- final修饰类,代表这个类不能被继承了,但这个类的对象能改变,只是这个类的结构不能被改变了
abstract
之前定义的类都为普通类,之后会出现抽象类,外部类,内部类,匿名类,静态内部类。
abstract可以修饰类,方法
普通的类没有能力承载抽象方法,抽象类能承载它
abstract修饰的类,实际不能单独存在,单独拿出来没有意义,他修饰的方法,没有执行过程,只是知道有这个方法
打个比方:定义一个塑料玩具类,玩具一定有一个玩的方法,但是每个玩具的玩法都不同。所以再没有确定这个塑料玩具是啥之前根本不知道它的方法怎么执行,但是你一定确定他可以玩,所以会有一个玩的方法。这个方法,塑料玩具类可以实现它,但是实现了并没有意义。每个生产厂商再继承它时都需要从写它,所以在料玩具类中没有必要去实现它,但是一定要声明他。如果谁继承了塑料玩具类,那么他必须要实现这个方法
所以abstract修饰的方法刚好和final修饰的方法反过来了,与final构成了反义词,abstract修饰的方法必修被重写,但final修饰的方法一定不能被重写,所以abstract修饰修饰的类一定要被继承
代码实现一下
父类(塑料玩具类)
public abstract class PlasticToy {
public abstract void play();//声明一个抽象方法,没必要实现这个方法,但他的子类必须实现它
}
子类(玩具厂商类)
public class PlasticGun extends PlasticToy {
@Override
public void play() {
System.out.println("biubiubiu");
}
}
其实,子类必须实现父类的抽象方法,这句话不对。如果子类也有能力承载抽象方法就可以不用实现父类中的抽象方法(子类也是抽象类),这时子类存在的意义也就是让别人来继承它
抽象类中可以有构造方法,但是他不能创建对象
抽象类的构造方法用来定义子类中必须要对这个类的一些属性初始化。
抽象类的构造方法为啥不能用来创建对象?
反例来证一下,如果可以创建对象,那么它就可以通过对象来调用抽象类中的抽象方法了,但是他没有方法体,根本不能执行,所以不能创建对象。
从原理上说,是因为创建对象时要把每个方法都放到方法栈中,现在拿到了一个抽象方法,他没有方法体,根本不知道他占多大内存,运行行计数器指向哪,所以没办法把他放入方法栈,所以不能创建对象
对比一下普通类和抽象类
普通类可以放普通方法,属性,静态变量,常量,可以有构造方法,能创建对象,不能放抽象方法
抽象类可以放普通方法,抽象方法,可以有构造方法但是不能创建对象
抽象类存在的价值让别人继承,抽象方法存在的价值让别人是实现,抽象类就是规定所有子类的模板
匿名类
匿名类(也叫匿名内部类):匿名类会被默认为这个父类或者接口的子类或实现类如。
如果抽象类非要创建对象那也可以,可以创建一个他的匿名子类对象,这个匿名类继承父类且重写父类中的抽象方法,且这个匿名对象只能用一次
场景类
public class Main {
public static void main(String[] args) {
PlasticToy toy = new PlasticToy()/*这个花括号里的东西就叫做匿名类*/ {
@Override
public void play() {
}
};
}
}