391!!讲单例模式饿汉式、懒汉式、final使用、抽象类(重要)、(重要)接口
饿汉式(单例模式)(有个缺点:往往单例模式的对象都是重量级,饿汉式有可能创建了没有使用,造成资源浪费)
package com.Liao_.SingleTon;
/*
演示饿汉式单例模式
*/
public class SingleTon01 {
public static void main(String[] args) {
GirlFriend person = GirlFriend.getInstance();
System.out.println(person);
GirlFriend person2 = GirlFriend.getInstance();
System.out.println(person2);
System.out.println(person == person2);//true.因为person和person2都是同一个对象
}
}
class GirlFriend {
private String name;
private static GirlFriend gf = new GirlFriend("小蓝");
private GirlFriend(String name){
this.name = name;
}
public static GirlFriend getInstance(){
return gf;
}
// public GirlFriend getInstance() {
// return gf;
// }
//这个要用对象来调用,,但是private 修饰的构造器不能在外部创建对象
//因此要使用静态方法和静态属性在类加载的时候就能调用。
}
- 为什么叫饿汉式?因为没有使用实例(对象)但它也依旧创建了。(有些时候只需要调用GirlFriend的一个属性,而不需要创建其对象。所以就产生了懒汉式)
懒汉式(单例模式)
package com.Liao_.SingleTon;
/*
* 演示懒汉式的单例模式
*
* */
public class SingleTon02 {
public static void main(String[] args) {
Cat cat1 = Cat.getInstance();
System.out.println(Cat.getInstance());
}
}
//希望在程序运行过程中,只能创建一个Cat对象
//使用单例模式
class Cat {
private String name;
//步骤:
//1.仍然构造器私有化
//2.定义一个静态属性对象
//3.提供一个public的static方法,可以返回一个Cat对象。
//4.懒汉式,只有当用户使用getInstance时,才返回Cat对象,
// 后面再次调用时,会返回上次创建的cat对象。
//从而保证了单例!
private static Cat cat = null;
private Cat(String name) {
this.name = name;
}
public static Cat getInstance(){
if(cat == null){
cat = new Cat("小猫");
}
return cat;
}
}
- 懒汉式存在线程安全问题。饿汉式存在资源浪费的可能。
- 小结
-
单例模式的两种实现方式(1)饿汉式 (2)懒汉式
-
饿汉式的问题:在类加载的时候就创建,可能存在资源浪费的问题
-
懒汉式的问题:线程安全问题。。后面的课程会解决。
final 关键字
final关键字注意事项、及细节
- final 修饰的属性又叫常量,一般用 XX_XX_XXX 来命名
- final 修饰的属性在定义时,必须赋初值,并且以后不能再修改。
赋值位置可选其一:①定义时。 ②在构造器中。 ③在代码块中
- 如果final 修饰的属性时静态的,则初始化的位置有要求。
①定义时 ②在静态代码块(类加载的时候一定会被调用)
不能在构造器中赋值(因为类加载后还不一定调用构造器,而final的属性必须有值)。
-
final 类不能被继承,但是可以实例化对象。
-
如果类不是final 类,但是含有final 方法,则该方法虽然不能重写,但是可以被继承。
final 使用细节
- 细节 (下面这个final 类中的 final() 方法有点画蛇添足)
因为:final 类不能被继承,子类自然不能重写它的方法。
- final 和 static 往往搭配使用,效率更高,底层编译器做了优化处理。
如果只调用所在方法。它就不会初始化static代码块。
final 练习题
(重要)抽象类
(重要)
- 抽象方法不能有方法体。
-
当父类的一些方法不能确定时,可以用abstract 关键字来修饰该方法,这个方法就是首相方法,用abstract 来修饰该类就是抽象类。
-
一般来说,抽象类会被继承,由其子类来实现抽象方法。
(重要)细节
- 抽象类不能被实例化
- 抽象类不一定要包含abstract 方法。也就是说,抽象类可以没有abstract 方法。
- 一旦类包含了abstract 方法,则这个类必须声明为abstract 。
- abstract 只能修饰类和方法,不能用于修饰其它。
-
抽象类可以有任意成员 [ 抽象类本质还是类 ],比如:非抽象方法、构造器、静态属性等等。
-
如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract 类。
(所谓实现方法,就是要求里面有方法体。)
- 抽象方法不能使用private、final、和static 来修饰,因为这些关键字都是和重写相违背的。
抽象类课堂练习
-
abstract类不能被final、static、private修饰, final 修饰抽象类会导致子类不能继承abstract类。
-
因为static 关键字和方法重写无关。
-
private 修饰abstract( ) 方法,导致抽象类无法被外部访问,就不能被实现。
-
见IDEA的package com.Liao.abstract;
抽象类最佳实践-模板设计模式
模板设计模式中要注意动态绑定机制。
package com.Liao_.moduleDesign;
//Template抽象类 ===》(父类)模板
abstract public class Template {
public void culculateTime(){
long startTime = System.currentTimeMillis();
job();
long endTime = System.currentTimeMillis();
System.out.println("job耗时" + (endTime - startTime));
}
// abstract()方法 让子类重写。
abstract void job();
}
package com.Liao_.moduleDesign;
public class AA extends Template{
public void jobEvolution(){ //使用OOP来初步改进。用于对比//之后用模板设计模式。
long startTime = System.currentTimeMillis();
job();
long endTime = System.currentTimeMillis();
System.out.println("AA类耗时" + (endTime - startTime));
}
public void job(){
int sum = 0;
for (int i = 1; i < 10000000; i++) {
sum += i;
}
}
}
package com.Liao_.moduleDesign;
public class BB extends Template{
public void job(){
// long startTime = System.currentTimeMillis();
int sum = 0;
for (int i = 1; i < 1000000; i++) {
sum *= i;
}
// long endTime = System.currentTimeMillis();
// System.out.println("BB类耗时" + (endTime - startTime));
}
}
(重要)接口
-
在jdk7.0前,接口里所有方法都没有方法体。即都是抽象方法
-
在jdk8.0及后接口可以有静态方法,默认方法(必须使用default 关键字修饰),也就是说接口中可以有方法的具体实现。
-
在接口中抽象方法可以省略abstract 关键字
- 如果一个类 implement 接口
- 需要实现其所有的抽象方法。
为什么要用接口?
- 老韩示例
接口使用细节、注意事项
-
接口不能被实例化
-
接口中所有的方法是 public 方法,接口中抽象方法,可以不用abstract修饰。
-
一个普通类实现接口,就必须将该接口的所有方法都实现,可以使用alt+enter快捷键解决。
-
抽象类实现接口,可以不实现接口的方法。(但是其子类总有一次要实现)
- 一个类同时可以实现多个接口。
- 接口中的属性,只能是final的,而且是 public static final 修饰符。
- 接口和接口是使用 extends (而且接口可以多继承)
- 接口的修饰符 只能是 public 和默认,这点和类的修饰符是一样的。
接口练习题
- JAVA提供的继承机制,可以理解为是对java中单继承的一种补充。
- 接口在一定程度上实现代码解耦 [ 即:接口规范性 + 动态绑定机制 ]
接口多态特性
- 继承体现的多态。
- 多态数组 (注意动态绑定机制)
- 接口的多态传递。
TIP:如果IG 继承了IH 接口,而Teacher 类实现了IG 接口, 那么,实际上相当于Teacher 类也实 现了IG 接口。这就是所谓的接口多态传递现象
课堂练习
- 小结。
System.out.println("======下面讲面向对象类的最后一个成员,内部类(最不容易理解)====");