一.什么是继承?
java中提供了一个关键字extends, 用这个关键字,可以让一个类和另一个类建立起父子关系。
二.继承的特点
1.子类能继承父类的非私有成员
2.子类的对象由子类、父类共同完成的。
代码演示: 创建了A,B两个类,B继承于A
public class A {
//非私有能直接继承
public int i;
public void print1(){
System.out.println("===print1===");
};
//私有成员
private int j;
private void print2() {
System.out.println("===print2===");
}
}
public class B extends A{
public void print3(){
System.out.println(i);
print1();
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.i); //成功访问父类的公开变量
System.out.println(b.k); //成功访问子类的公开变量
System.out.println(b.j);//b.j是私有变量会报错
}
}
三.继承的好处
减少重复代码的使用,提高效率
四.继承相关的注意事项
1. 掌握不同权限修饰符的作用
(此图非常重要)
2. 单继承和Object类
- 单继承
Java是单继承的;一个类只能继承一个直接父类;Java中的类不支持多继承,但是支持多层继承.
public class C extends A,B{
//报错:Class cannot extend multiple classes
}
- Object类
所有类都直接或者间接继承于Object类,能够使用Object类中的方法
3. 方法重写
- 代码演示:
```java
public class A {
public void print1(){
System.out.println("111");
}
public void print2(int a, int b ) {
System.out.println("111111");
}
}
public class B extends A{
//方法重写
@Override
public void print1() {
System.out.println("666");
}
@Override
public void print2(int a, int b) {
System.out.println("666666");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.print1();
b.print2(1,2);
}
}
结果输出:
666
666666
-
注意事项:
-重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。 -子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限( public > protected > 缺省) -重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。 -私有方法、静态方法不能被重写,不然会报错。
-
开发中常见的应用场景:
toString()方法重写:
public class Student {
public Student() {
}
public Student(String age, String name) {
this.age = age;
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String age;
public String name;
@Override
public String toString(){
return "Student{name=" + name + ",age=" + age + "}";
}
//重写toString方法:
public class Test {
public static void main(String[] args) {
Student stu = new Student("18","黄拓森");
System.out.println(stu);
}
}
}
原来的结果:d11_extends_feature.Student@1b6d3586 //对象的地址
现在的结果:Student{name=黄拓森,age=18}
4. 子类访问成员的特点
在子类方法中访问其他成员(成员变量、成员方法),依照就近原则。
代码演示:
public class F {
String name = "父类名字";
public void print1(){
System.out.println("==父类的print1方法执行==");
}
}
public class Z extends F{
String name = "子类名称";
public void showName() {
String name = "局部名称";
System.out.println(name);//局部变量
System.out.println(this.name);//子类变量
System.out.println(super.name);//父类变量
}
}
public class Test {
public static void main(String[] args) {
Z z = new Z();
z.showName();
}
}
最后结果:
局部名称
子类名称
父类名字
5. 子类构造器
子类的全部构造器,都会先调用父类的构造器,再执行自己。
子类构造器都会默认存在:super();调用父类的无参数构造器
因此,如果父类没有无参数构造器,有有参构造器,那么子类构造器第一行必须要手写super()调用父类有参构造器。
这样做有什么意义?子类构造器可以通过调用父类构造器,把对象中包含父类这部分的数据先初始化赋值,再回来把对象里包含子类这部分的数据也进行初始化赋值
代码演示:
public class Test {
public static void main(String[] args) {
Teacher t = new Teacher("111",14,"222");
System.out.println(t.getName());
System.out.println(t.getAge());
System.out.println(t.getSkill());
}
}
class Teacher extends People {
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
private String skill;
public Teacher(String name, int age , String skill){
super(name,age); //调用父类构造器,初始化赋值name 和 age
this.skill = skill; //再把子类的数据进行初始化赋值
}
}
class People {
public People(String name, int age) {
this.name = name;
this.age = age;
}
public People() {
}
private String name;
private int age;
最后的结果:
111
14
222
}
补充知识: this()调用兄弟构造器
this()用法代码示例:
public class Student {
public Student(int age, String name, String schoolName) {
this.age = age;
this.name = name;
this.schoolName = schoolName;
}
public Student(int age, String name) {
this(age,name,"javaboy大学");
//我想完成功能:如果没填写schoolName,默认为javaboy大学,就可以调用this()
//this()直接调用兄弟构造器
}
public int age;
public String name;
public String schoolName;
}
注意事项:this()和super()都必须再在第一行,并且不能同时出现。