1.方法
可变参数
用类型...
定义,可变参数相当于数组类型:
class Group {
private String[] names;
public void setNames(String... names) {
this.names = names;
}
}
2.构造方法
- 如果我们自定义了一个构造方法,那么,编译器就不再自动创建默认构造方法
- 可以定义多个构造方法,编译器根据参数自动判断
- 可以在一个构造方法内部调用另一个构造方法,便于代码复用
3.方法重载
- 方法名相同,但各自的参数不同,称为方法重载(
Overload
)。 - 注意:方法重载的返回值类型通常都是相同的。
- 方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。
4.继承
Protected
继承有个特点,就是子类无法访问父类的private
字段或者private
方法.
为了让子类可以访问父类的字段,我们需要把private
改为protected
。用protected
修饰的字段可以被子类访问.
protected
关键字可以把字段和方法的访问权限控制在继承树内部
Super
表示父类,主要用于子类的构造方法中
-
子类不会继承任何父类的构造方法.
-
如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句
super();
,这样做会有风险,因为自动加入的super()
构造方法可能不存在。必须手动调用存在的某个构造方法。
向上转型和向下转型
把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting)。
Student s = new Student();
Person p = s; // upcasting, ok
Object o1 = p; // upcasting, ok
Object o2 = s; // upcasting, ok
和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)。
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!
向下转型很可能会失败。失败的时候,Java虚拟机会报ClassCastException
。
为了避免向下转型出错,Java提供了instanceof
操作符,可以先判断一个实例究竟是不是某种类型
Person p = new Student();
if (p instanceof Student) {
// 只有判断成功才会向下转型:
Student s = (Student) p; // 一定会成功
}
从Java 14开始,判断instanceof
后,可以直接转型为指定变量,避免再次强制转型。
public static void main(String[] args) {
Object obj = "hello";
if (obj instanceof String s) {
// 可以直接使用变量s:
System.out.println(s.toUpperCase());
}
}
5.多态
覆写Override
-
子类重写了父类的方法称为覆写。
-
加上
@Override
可以让编译器帮助检查是否进行了正确的覆写。
多态
-
多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。
-
多态具有一个非常强大的功能,就是允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码
-
在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过
super
来调用
final
修饰符有多种作用
final
修饰的方法可以阻止被覆写;final
修饰的class可以阻止被继承;final
修饰的field必须在创建对象时初始化,随后不可修改。
6.抽象
问题:由于多态的存在父类的方法可能没有实际意义,需要去掉父类的方法,但不能正真的去掉,因为会失去多态的特性。
**解决:**我们可以为父类方法声明abstract
方法,但同时也必须将父类声明为抽象类,才能正确编译它。
abstract class Person {
public abstract void run();
}
**抽象类的作用:**强迫子类实现其定义的抽象方法,抽象方法实际上相当于定义了“规范”。
**面向抽象编程:**使得调用者只关心抽象方法的定义,不关心子类的具体实现。
7.接口
在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现,这样,多态就能发挥出威力。
如果一个抽象类没有字段(可以有静态字段),所有方法全部都是抽象方法(可以有default方法),就可以把该抽象类改写为接口:interface
。
接口继承
- 一个
interface
可以继承多个interface
.
default方法
-
实现类可以不必覆写
default
方法。 -
default
方法和抽象类的普通方法是有所不同的。因为interface
没有字段,default
方法无法访问字段,而抽象类的普通方法可以访问实例字段。
8.静态字段和静态方法
使用static
修饰。
静态字段
- 所有实例共享该字段
- 不推荐用
实例变量.静态字段
去访问静态字段 - 推荐用类名来访问静态字段
静态方法
-
调用静态方法不需要实例,通过类名就可以调用,无法访问
this
,但可以访问静态字段和其他静态方法 -
静态态方法常用于工具类和辅助方法。
接口的静态字段
因为interface
是一个纯抽象类,所以它不能定义实例字段。但是,interface
是可以有静态字段的,并且静态字段必须为final
类型:
public interface Person {
public static final int MALE = 1;
public static final int FEMALE = 2;
}
实际上,因为interface
的字段只能是public static final
类型,所以我们可以把这些修饰符都去掉,上述代码可以简写为:
public interface Person {
// 编译器会自动加上public statc final:
int MALE = 1;
int FEMALE = 2;
}
编译器会自动把该字段变为public static final
类型。