Java学习笔记四(继承)

发布于:2025-09-12 ⋅ 阅读:(17) ⋅ 点赞:(0)

1 继承

继承的实现:public class 子类 extends 父类 {… }

注释:子类可直接使用,父类(保护,公开)的属性和方法

优点:减少重复代码,缺点:只能单继承

// 父类
public class Test {
	private String str1; //私有
	String str2;         //默认
	protected String str3;// 保护
	public String str4;    //公开
	
	private void fn1() {} //私有
	void fn2() {}         //默认
	protected void fn3() {}// 保护
	public void fn4() {}   //公开
}
// 子类
public class SubTest extends Test {
    public void subFn1() {
    	String t3 = str3;
    	String t4 = str4;
    	fn3();
    	fn4();
    }
}

2 子类实例化

子类构造器默认先调用父类无参构造器(可省略),父类没有无参构造器(必须先显示调用有参构造器)

public class 子类 extends 父类 {
    public 子类() {
        [super();] // 可省略
        子类处理…
    }
}

3 方法重写

注释:子类定义了与父类相同的方法(方法重写)

// 父类
public class Test {
    public String name = "张三";
    public void doTest() {
        System.out.println(name);
    }
}

测试类1:子类未重写方法,调父类方法使用的是父类属性(不会输出子类同名属性)

// 子类
public class SubTest1 extends Test {
    public String name = "李四";
}
public class Main {
    public static void main(String[] args) {
        SubTest1 s = new SubTest1(); 
        System.out.println(s.name); //输出 李四
        s.doTest();  //输出 张三(子类没有该方法,父类该方法输出父类名字)
    }
}

测试类2:子类重写属性方法后,使用的是子类的属性

//子类
public class SubTest2 extends Test {
	public String name = "李四";
	public void doTest() {
		System.out.println("son:"+name);
	} 
}
public class Main {
    public static void main(String[] args) {
    	SubTest2 s = new SubTest2();
    	System.out.println(s.name); // 输出 李四
    	s.doTest();// 输出 son:李四
    }
}

测试类3:子类对象定义为父类类型,输出父类属性,调用的是子类方法

//子类
public class SubTest2 extends Test {
	public String name = "李四";
	public void doTest() {
		System.out.println("son:"+name);
	} 
}
public class Main {
    public static void main(String[] args) {
    	Test s = new SubTest2();
    	System.out.println(s.name);  // 输出 张三
    	s.doTest();   // 输出 son:李四
    }
}

测试类4:子类对象强转父类类型,输出父类属性,调用的是子类方法

//子类
public class SubTest2 extends Test {
	public String name = "李四";
	public void doTest() {
		System.out.println("son:"+name);
	} 
}
public class Main {
    public static void main(String[] args) {
    	SubTest2 s = new SubTest2();
    	Test ss = (Test)s;
    	System.out.println(ss.name);  // 输出 张三
    	ss.doTest();  // 输出 son:李四
    }
}

4 方法重载

方法名(相同)参数(个数或类型)(不同)与返回值无关

public class Test {

    public String fn(String str){ 
    }
    // 重载1,参数类型不同
    public String fn(int num) {
    }
    // 重载2,参数个数不同
    public String fn(int age, int num) {
    }

}

5 super关键字

注释:只可在子类内部使用,使子类可以使用父类原生方法与属性

(1) 调用父类构造器:super([参数…]);

(2) 调用父类属性:super.属性; // 获取与更改父类的属性,不影响子类同名属性

(3) 调用父类方法:super.方法(); // 调用父类的方法,与子类是否重写无关

// 父类
public class Test {
	private String str1 = "私有";
	String str2 = "默认";
	protected String str3 = "保护";
	public String str4 = "公开";
	
	private String fn1() { return str1; }
	String fn2() { return str2; }
	protected String fn3() { return str3; }
	public String fn4() { return str4; }
}
// 子类
public class SubTest extends Test {

	protected String str3 = "保护(son)";
	public String str4 = "公开(son)";
	
	protected String fn3() { return str3; }
	public String fn4() { return str4; }
	
    // 调用父类构造器(默认不写也调用)
	public SubTest() {
		super();
	}
    // 调用父类方法
	public void test() {
		System.out.println(super.str3);  // 输出 父类 保护
		System.out.println(super.str4);  // 输出 父类 公开
		System.out.println(super.fn3());  // 输出 父类 保护
		System.out.println(super.fn4());  // 输出 父类 公开
	}
	public void testSub() {
		System.out.println(str3);  // 输出 子类 保护(son)
		System.out.println(str4);  // 输出 子类 公开(son)
		System.out.println(fn3());  // 输出 子类 保护(son)
		System.out.println(fn4());  // 输出 子类 公开(son)
	}
}

6 代码执行顺序

6.1 静态方法

// 初次调用:类名.静态方法() 

1.类加载(静态变量初期化,只执行1次)

2.类加载(静态代码块,只执行1次)

3.静态方法执行

// 之后再调用:类名.静态方法() // 只重复执行3

3.静态方法执行

6.2 实例化对象

// 初次实例化:new 对象()

1.类加载(静态变量初期化,只执行1次)

2.类加载(静态代码块,只执行1次)

3.代码块(执行)

4.构造器(执行)

// 之后再实例化:new 对象()  // 只重复执行3,4

3.代码块(执行)

4.构造器(执行)

6.3 子类静态方法

// 初次调用:子类.静态方法() 

1.父类加载(静态变量初期化,只执行1次)

2.父类加载(静态代码块,只执行1次)

3.子类加载(静态变量初期化,只执行1次)

4.子类加载(静态代码块,只执行1次)

5.子类静态方法(执行)

// 之后再调用:子类.静态方法()  // 只重复执行5

5.子类静态方法(执行)

6.4 子类实例化对象

// 初次调用:new 子类对象() 

1.父类加载(静态变量初期化,只执行1次)

2.父类加载(静态代码块,只执行1次)

3.子类加载(静态变量初期化,只执行1次)

4.子类加载(静态代码块,只执行1次)

5.父类代码块(执行)

6.父类构造器(执行)

7.子类代码块(执行)

8.子类构造器(执行)

// 之后再调用:new 子类对象()  // 只重复执行5,6,7,8

5.父类代码块(执行)

6.父类构造器(执行)

7.子类代码块(执行)

8.子类构造器(执行)

总结:1 只有初次类加载初始化静态变量,执行静态代码块。2 父类(变量,代码块,构造器)优先于子类执行。3 代码块优先于构造器执行。


网站公告

今日签到

点亮在社区的每一天
去签到