static关键字
static关键字是一个标记,有static修饰的是静态成员,属于类;没有static修饰的属于实例成员,属于实例(对象)。
声明为static的变量称为静态变量或类变量。静态变量是跟类相关联的,类的所有实例共同拥有一个静态变量——最后一次赋值的值。
声明为static的方法称为静态方法或类方法。静态方法可以直接调用静态方法,访问静态变量,但是不能直接访问实例变量和实例方法(因为有static修饰的方法执行结果应该相同,如果调用实例会不相同)。静态方法中不能使用this关键字,因为静态方法不属于任何一个实例。父类中的static方法可以在子类中重写,但是不能被覆盖(所以重写也没用,还是会调用父类的方法)。
publicclassStaticTest { publicstaticvoid main(String[] args) { A a = new B(); a.f1(); //A的f1 a.f2(); //B的f1 } } //父类 class A { publicstaticvoid f1() { System.out.println("A的f1"); } publicvoid f2() { System.out.println("A的f2"); } } //子类 class B extends A { //重写父类的静态方法,但不会被覆盖 publicstaticvoid f1() { System.out.println("B的f1"); } //重写父类的方法,会被覆盖 publicvoid f2() { System.out.println("B的f2"); }
} |
类回收
类在第一次被使用以后,就常驻内存,直到java命令结束。
类不会被java自动回收,属于类的静态成员,也不会被回收。
对象被创建出来以后,java会自动检查对象是否需要回收,如果检查到对象需要被回收,会自动把对象从内存删除。
对象里面的实例成员也会被回收、删除。
final关键字
是修饰符,可以修饰类、方法、变量
- 修饰类,表示类不能被继承public final class...
- 修饰方法,表示方法不能被子类重写(覆盖)但可以被继承public final void...
-
修饰变量,表示只能赋值一次
-
修饰成员(全局)变量,那么必须在合适的地方给成员变量初始化,因为final的成员变量系统不会赋予默认值。
-
修饰实例变量(无static修饰):实例变量必须在三个地方进行初始化:
1.直接等号赋值
2.使用实例初始化代码块赋值
3.使用构造器赋值
-
修饰类变量(有static修饰):必须在两个地方进行初始化:
1.直接等号赋值
2.使用类初始化代码块赋值
-
- 修饰局部变量,赋值没有区别,因为局部变量本身就是需要被赋值以后才能使用的。只是有final修饰的时候,意味着变量不能被再次赋值。
-
-
eg.实例变量
publicclassTestFinal { //直接等号赋值 finalinta = 5; finalintb; { //使用实例代码块初始化final的实例变量 b = 10; }
finalintc; //在构造器里面初始化c变量 TestFinal() { c = 15; }
} |
eg.类变量
publicclassTestFinal { //等号直接赋值 finalstaticintd = 110;
//使用静态代码块赋值 finalstaticinte; static { e = 120; } |
abstract关键字
修饰符,可以修饰类、方法
无论什么情况下,final和abstract都是对头,不能同时存在的。原因:对于类, final类不能被继承,而abstract类要通过子类实例化。对于方法, static的方法是通过类名进行方法,并且static的方法不具备多态的特性。
- 修饰类,表示类不能被new,要想获得实例,只能通过new子类来实现。相当于new了一个子类的实例,赋予给父类类型的变量。抽象类里面,不一定有抽象方法。类里面如果有抽象方法,那么类必须是抽象的。
- 修饰方法,表示方法不能有方法体,直接使用分号结束,必须由子类来重写(覆盖)。
eg.抽象类
publicclassTestAbstract { publicstaticvoid main(String[] args) { //抽象类不能被new,报错 //Parent p = new Parent();
//非抽象类child继承抽象类parent,小类给大类,多态 Parent p = new Child(); } }
//抽象父类 abstractclass Parent { }
//写一个子类,继承Parent class Child extends Parent { } |
eg.抽象方法
publicclassTestAbstract { publicstaticvoid main(String[] args) {
//多态 AbstractMethod am = new AbstractMethodChild2();
//编译的时候,只检查am的类型里面是否有定义test方法,但是是否有实现,不考虑 //运行的时候,am是AbstractMethodChild2类型的,实际上已经覆盖了父类的抽象方法,test被实现了! am.test(); } }
//有抽象方法的类,一定是抽象类,抽象方法一定要子类去重写(覆盖) abstractclass AbstractMethod { //抽象方法没有方法体,直接使用分号结束 //方法的参数、返回值、修饰符等全部和普通的方法一样 abstractvoid test(); }
//继承了抽象类,要么实现所有的抽象方法,要么子类也是抽象的 abstractclass AbstractMethodChild1 extends AbstractMethod { }
class AbstractMethodChild2 extends AbstractMethod { void test() { System.out.println("子类的test方法实现"); } } |
模板模式
解决的问题:当一个类的大部分的操作都能够被确定下来,但是一小部分需要给子类来实现的时候。这种情况下就使用模板模式。
步骤
1.把大量的、已经确定的工作写到一个final的方法里面
2.不确定的事情,交给一些抽象的方法去执行
3.因为类里面有了抽象方法,所以类必须是抽象的,这个时候要实例就只能从子类创建
4.执行业务代码的时候,抽象方法因为被子类实现了,所以行为就有子类来决定
单例模式——避免重复创建实例
单例模式,是一种设计模式。利用静态成员的特性来实现。
目的:避免在内存里面出现一个类的多个实例。每当new一次类,就一定产生一个新的实例,现在需要避免这种实例的产生。
如果一个类里面,没有记录任何的用户相关的数据,那么就可以使用单例模式,降低不必要的new,提高程序的性能。
实现步骤
1.私有构造器,避免类外面使用new去调用构造器。
2.在类里面提供一个类型为当前类的静态变量(唯一的),并且调用构造器进行初始化
3.提供一个公共的、静态的方法,用于获取静态变量。
//这个是支付服务 //单例模式避免重复创建实例 class PaymentService { //1.私有构造器 private PaymentService() { System.out.println("创建了支付服务 " + this); }
//2.在类里面提供一个类型为当前类的静态变量,并且调用构造器进行初始化 privatefinalstatic PaymentService instance = new PaymentService();
//3.提供一个静态的、公共的方法,获得实例 publicstatic PaymentService getPaymentService() { returninstance; } }
publicclassTestPaymanetService { publicstaticvoid main(String[] args) { //不能再new,因为构造器私有,下式报错 //PaymentService ps = new PaymentService();
//调用静态方法获得唯一的实例 PaymentService ps1 = PaymentService.getPaymentService(); PaymentService ps2 = PaymentService.getPaymentService();
//每次获得的都是相同的实例 System.out.println(ps1); System.out.println(ps2); } } |