单例模式
- 目的:使得类的一个对象成为该类系统中的唯一实例
- 定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供
- 要求:
- 某个类只能有一个实例
- 必须自行创建实例
- 必须自行向整个系统提供该实例
- 实现:
- 只提供私有的构造方法
- 含有一个该类的静态私有对象
- 提供一个静态的公有方法用于创建、获取静态私有对象
- 代码实现方案:
- 饿汉式
- 饿汉式在类加载时就创建实例,第一次加载速度快
- 空间换时间
- 懒汉式
- 懒汉式第一次使用时才进行实例化,第一次加载速度慢
- 时间换空间
- 饿汉式线程安全;懒汉式存在线程风险
- 解决方案
- 同步锁
- 双重校验锁
- 静态内部类
- 枚举
- 解决方案
- 饿汉式
- 优点:
- 在内存中只有一个对象,节省内存空间
- 避免频繁的创建销毁对象,提高性能
- 避免对共享资源的多重利用
缺点:
编译时多态(设计时多态):方法重载
- 运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法
-
必要条件
满足继承关系(继承是多态的前提)
-
向上类型转换(Upcast)
将子类型转换为父类型
隐式/自动类型转换,是小类型到大类型的转换
对于向上的类型转换,不需要显示指定,即不需要加上前面的小括号和父类类型名
向下类型转换(Downcast)
将父类型转换为子类型
将一个指向子类对象的父类引用赋值给一个子类的引用
- 强制类型转换,是大类型转为小类型
- 父类型的引用必须指向转型的子类型的对象,即指向谁才能转换成谁,不然会编译报错
- 通过instanceof判断父类型的引用是否指向子类型的对象。
注意点
- 父类引用指向子类实例时,可以调用子类重写父类的方法以及直接继承父类的方法,但不能调用子类特有的方法
- 静态static方法属于特殊情况,静态方法只能继承,不能重写,调用的时候用谁的引用,则调用谁的版本
抽象类&抽象方法
使用抽象类限制类的实例化(原因:一些类实例化是没有意义的)—-abstract
- 抽象方法 —- 加abstract
- 抽象方法没有方法体
- 抽象方法必须在抽象类中
- 抽象方法必须在子类中被重写,除非子类也定义为抽象类
使用规则
访问权限默认为:public 或 默认
- 常量默认添加static final关键字
- 抽象方法默认添加abstract关键字
- 只有default方法及static方法可以添加方法体
- 实现接口的类如果不能实现接口中的所有方法则要定义为抽象类
- 接口可以实现多继承,即一个接口可以继承多个父接口
- 一个类可以继承一个父类同时实现多个接口
当一个类实现多个接口时,如果多个接口中含有相同方法,则这个类必须重写这个相同方法,否则编译会报错
内部类
成员内部类
最常见,也称为普通内部类
public class Person{
int age;//年龄
public Heart getHeart(){
return new Heart();
}
//内部类:心脏
class Heart{
public String beat(){
System.out.println("心脏在跳动~");
}
}
}
相当于一个成员变量,可以使用任意修饰符修饰
- 可以直接访问外部类,不受修饰符影响
- 外部类不能直接使用内部类的成员和方法,需要借助内部类对象
- 需要通过外部类对象来创建内部类实例
- 外部类内部类如果具有相同的成员,内部类默认访问自己的,可以通过“外部类.this.对象成员”以及“外部类.静态成员(static)”方式访问外部类成员
-
静态内部类
public class Person{
int age;//年龄
public Heart getHeart(){
return new Heart();
}
//静态内部类:心脏
static class Heart{
public String beat(){
System.out.println("心脏在跳动~");
}
}
}
静态内部类可以不通过外部类直接创建对象
- 静态内部类不能直接访问外部类的非静态成员,可以通过外部类对象.成员的方式访问
-
方法内部类
public class Person{
int age;//年龄
public void getHeart(){
//方法内部类:心脏
class Heart{
public String beat(){
System.out.println("心脏在跳动~");
}
}
new Heart().beat;
}
}
定义在外部类方法中的类也称为局部内部类
- 方法内部可见,只有在方法内可以使用
- 不能使用static,但能使用final、abstract
- 编译后产生:外部类$数字.class
匿名内部类
```java interface Animal{//动物接口 //跑方法 public void run(); } public static void main(String[] args){ Animal dog = new Animal(){
}; dog.run(); }public void run(){
System.out.println("小狗快跑~");
}
```
- 场景
- 只用到类的一个实例
- 类在定义后马上使用
- 给类命名不会导致类更容易被理解
- 使用原则:
- 不能有构造方法,可以有构造代码块
- 不能定义静态成员、静态方法
- 不能使用public、protected、private、static、abstract、final修饰
- 也是局部内部类,所以局部内部类的限制对匿名内部类都生效
- 一定是在new的后面,用其实现一个接口或继承一个类,二者不可兼得
- 只能创建匿名内部类的一个实例
- 匿名内部类在编译后由系统自动起名为:Outter$1.class
- 一般来说,用于继承其他类或实现接口,不需要新增新的方法,重写类或接口的方法即可
- 通过匿名内部类返回的是一个对象的引用,所以可以直接使用或将其复制给一个对象变量