面向对象
什么是面向对象
https://www.bilibili.com/video/BV1wZ4y1B7A7
以对象为核心。
类是对象创建的模板,对象是类的实例。
面向对象三大特性是什么
- 封装:类的创建者将类具体实现隐藏,使用者只需要使用外部接口即可
- 继承:类有子类和父类,有从属关系。提高代码复用性。
- 多态:同一个方法可以被不同的对象以不同的方式执行。子类可以替代父类出现在任何需要父类的地方
怎么理解多态的特性
- 什么是多态:接口的多种不同的实现方式即为多态。多个对象调用同一个方法,得到不同的结果。
- 多态使用:
父类类名 对象 = new 子类类名();
- 向上转型(默认):子类型赋值给父类型。对象只能访问父类中的属性和方法,但会优先访问子类重写的方法。
- 向下转型:子类型赋值给父类型后,强转回子类型。
class Animal {public void eat() {System.out.println("Animal is eating");}
}class Dog extends Animal {public void bark() {System.out.println("Dog is barking");}
}public class Main {public static void main(String[] args) {// 向上转型Animal myAnimal = new Dog(); myAnimal.eat();// 向下转型if (myAnimal instanceof Dog) {Dog myDog = (Dog) myAnimal;myDog.bark();}}
}
Java为什么只能单继承
https://www.bilibili.com/video/BV14o4y1h7ri/
- 使用简单:多继承会导致“钻石问题”,子类有多个相同方法需要继承。
- 多继承在其他语言中也不经常使用
- Java可以通过实现多个接口实现“多继承”
抽象类和接口
接口和抽象类有什么区别
https://www.bilibili.com/video/BV14T4y1e725/
相同点:
- 都可以定义抽象方法,让子类去实现
- 都不能实例化
不同点:
- 抽象类用继承
extend
,接口用实现implements
- 接口可以多实现,抽象类只能单继承
- 抽象类可以实现接口,接口只能继承接口
- 抽象类可以定义成员属性,接口只能定义静态常量
- 抽象类可以定义构造方法,控制子类实例化。接口没有构造方法。
接口的补充:
- Java8:
default
关键字实现接口默认方法,子类可以不重写。提高兼容性。 - Java9:
private
关键字可以封装私有方法,可以提高默认方法的函数内的代码复用性。
方法重写和重载
方法重载和重写有什么区别
- 重载:类中定义了多个方法名相同,但参数不同的方法。
- 重写:子类存在方法与父类的方法的名字相同、参数相同
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
多态性:相同的名称但有着不同的实现。
内部类
内部类汇总
- 成员内部类:在成员位置上定义类
- 可以访问外部类静态属性和非静态属性
- 外部类成员方法调用成员内部类的方法需要先创建对象
public class User {static String name;int age;class IdCard {String id;public void getIdCardData() {System.out.println(name);System.out.println(id);System.out.println(age);}}IdCard idCard = new IdCard();public void getUserData() {System.out.println(idCard.id);}
}
- 局部内部类:在类的方法中定义类
- 可以访问外部类静态属性和非静态属性
public class User {static String name;int age;public void say() {class IdCard {String birthday;public void getIdCardData() {System.out.println(name);System.out.println(age);System.out.println(birthday);}}IdCard idCard = new IdCard();idCard.getIdCardData();}
}
- 静态(成员)内部类:在成员位置上定义静态类
- 只能访问外部类静态属性,不能访问非静态属性
public class User {static String name;int age;static class IdCard {String id;public void getIdCardData() {System.out.println(name);System.out.println(id);// System.out.println(age);}}IdCard idCard = new IdCard();public void getUserData() {System.out.println(idCard.id);}
}
- 匿名内部类:只有类体没有类名的类,通常用于创建只需要使用一次的类的实例。
public abstract class Animal {String name;abstract void eat();
}public class Main {public static void main(String[] args) {Animal animal = new Animal() {@Overridevoid eat() {System.out.println("The animal is eating");}};animal.eat();}
}
为什么需要内部类?什么是匿名内部类?
内部类的主要作用是可以访问外部类的私有成员。
匿名内部类是只有类体没有类名的类,通常用于创建只需要使用一次的类的实例。可以简化代码书写,不需要单独定义一个实体类。
静态内部类和非静态内部类有什么区别?
外部属性:
- 静态内部类只能访问外部类的静态属性
- 非静态内部类可以访问外部类的静态属性和非静态属性
对外部类实例的依赖:
- 静态内部类可以直接创建
- 非静态内部类需要外部类实例才能创建
静态内部类的使用场景是什么?
用来实现单例模式
- 优点:天然线程安全,实现延迟加载
- 缺点:第一次加载又有延迟
public class Singleton {public static class Inner {public static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return Inner.INSTANCE;}private Singleton() {}
}