Java学习笔记_11 final、super、向上造型

final

经典面试题1:final关键字的特点?

			final修饰的变量:不能被更改。
			final修饰的方法:不能被重写。
			final修饰的类:不能被继承。
			static final 配合修饰常量。

经典面试题2:String类能不能被继承?

不能。String类被final修饰的。

String类开头部分源码如下:
在这里插入图片描述


package day11_9;

public class FinalDemo {
	final static int  a = 1;//	static final 配合修饰常量。
	public static void main(String[] args) {
		FinalDemo f = new FinalDemo();
		System.out.println(a);
		//f.a = 2;//不注释会报错,因为a为final类型,无法被更改。
	}
}

运行 结果:

1

super

super指代父类的对象。
super方法,可以调用父类的构造方法,根据super方法的参数列表确定具体调用哪一个构造方法

经典面试题:this()和super()可不可以同时出现?

不能。因为this()和super()都必须放在构造方法的第一行。有冲突,二者不能同时出现。

向上造型:父类声明子类对象。

子类的对象可以向上造型为父类的类型。即父类引用子类对象,这种方式被称为向上造型。

父类声明子类对象:ex:Father s = new Son();

该对象(s)拥有的属性和方法都是父类的。但是当调用子类重写父类的方法时,编译期间执行的是父类的方法,运行期间执行的是子类的方法。
这是因为:
向上造型后 ,子类将不再具备其自己定义的方法,只有父类的方法。但若重写了父类的方法,向上造型的对象的方法为重写后新的方法。
在这里插入图片描述
在这里插入图片描述

仔细一看,s1.test(),显示的是父类中的test()方法,然而实际运行的时候,调用的却是子类中重写后的方法。

下面上例子来印证一下:

例子一:
Father.java

package day11_6;

public class Father {
	int age = 40;
	String name = "王老五";
	
	public void test(){
		String message = "父类的方法";
		System.out.println(message);
	}
}

Son.java

package day11_6;

public class Son extends Father {
	int age = 18;
	
	public void test(){
		System.out.println("这是子类的方法");
	}
}

★★★Test.java★★★

package day11_6;

public class Test {
	public static void main(String[] args) {//注::::【】中的为输出结果
		Son s0 = new Son();//创建一个子类的对象,叫s0
		System.out.println(s0.name);//【王老五】由于继承关系,且子类没有 重写 父类的name,故输出父类中的name 
		//测试:输出对象son的age的值
		System.out.println(s0.age);//【18】就近原则,优先使用子类自己的
		s0.test();//【这是子类的方法】覆盖掉父类的了,就近原则
		
		Father s1 = new Son();//向上造型
		System.out.println(s1.age);//【40】向上造型后,子类拥有的属性就都是父类中的了。(重写方法除外)
		s1.test();//【这是子类的方法】编译期间执行的是父类的代码(按Ctrl,鼠标点击test(),跳转到父类),而运行期间执行子类重写后的代码。
		
		Father f = new Father();
		f.test();//【父类的方法】
	}
}

例子二:

向上继承,编译时,是父类的方法。
在这里插入图片描述
执行时,却是子类的重写方法。
在这里插入图片描述

完整代码:
Father:

package day11_9;

public class Father {
	String name;
	int age;
	public Father(){
		System.out.println("这是父类的构造方法");
	}	
	
	public Father(String name, int age) {
		super();//调用Object中的构造方法
		this.name = name;
		this.age = age;
		System.out.println("这是父类的有参构造方法");
	}

	public void work(){
		System.out.println("父亲的工作是挣钱养家");
	}
	public void job() {
		// TODO Auto-generated method stub
		System.out.println("job");
	}
	
}

Son:

package day11_9;

public class Son extends Father {
	char sex;
	
	public Son(){
		//super();//隐藏的,默认存在      指向Father中的无参构造方法
		super("小明",8);//给父类赋值     指向Father中的有参构造方法
		
		System.out.println("这是子类的无参构造方法");
	}
	public void work(){
		super.age = 49;//只要调用了这个构造方法,Father的age就会被更改为49
		System.out.println("儿子的工作是快乐长大");
	}
}

Daughter:

package day11_9;

public class Daughter extends Father {

	char sex;
	String happy;
	
	public void work(){
		System.out.println("美美的长大");
	}
	public void interesting(){
		System.out.println("喜欢跳舞、画画");
	}
	
}

☆☆☆Test☆☆☆:

package day11_9;

public class Test {

	public static void main(String[] args) {//注:::::【】内为代码运行结果
		//使用向上造型的方式创建对象
		Father s = new Son();/*【这是父类的无参有参构造方法	
													这是子类的无参构造方法】*/
		/*new关键字调用Son的构造方法(创建对象、传值),创建Son的对象。赋值给了Father。
		 * 由于,调用了Son中的构造方法,
		 * 而	在Son的构造方法中最后一行的,输出语句(System.out.println("儿子的工作是快乐长大");)上面,
		 * 有一行super("小明",8);
		 * 这行代码,调用了父类中的有参构造方法。
		 * 其内部的这两行语句:this.name = name;	this.age = age; 
		 * 将父类中定义的	String name;	int age; 		给赋值了
		 * 
		 * 故:下面的测试语句会输出“小明“。
		 * 
		 * 若:没有super("小明",8);,则会默认先调用父类中的无参构造方法。
		 * 
		 * */
		//System.out.println(s.name );//【小明】
		
		s.work();//【儿子的工作是快乐长大】  	子类Son重写了父类中的work方法
		System.out.println(s.age);
		//【49】上面调用work()构造方法时,Son中的super.age = 49;改变了Father的age
		Father d;
		d  = new Daughter();
		/*【这是父类的无参构造方法】也是向上造型 	当 new 关键字调用Daughter的构造方法时,
		由于继承关系(默认Daughter的构造方法中,第一行super();),
		先通过父类的无参构造方法为其赋值,再执行子类构造方法中剩余的语句为子类赋值*/
		Son s1 = new Son();/*【这是父类的有参构造方法
												这是子类的无参构造方法】*/
		/**
		 * 流程:new关键字调用Son的构造方法给对象s1赋值
		 * 1、若Son构造方法的内部无内容  或者  压根Son就没有构造方法
		 * 			则直接调用父类Father的构造方法来为其赋值。
		 * 		【这是父类的无参构造方法】
		 * 
		 * 2、若Son的构造方法中,只有一句System.out.println("这是子类的无参构造方法");
		 * 			则先执行默认的super()语句,调用父类的无参构造方法。
		 * 			因为继承关系,子类的构造方法中默认在第一行有super(); 指向Father中的无参构造方法。
		 * 		【这是父类的无参构造方法
					这是子类的无参构造方法】
		 * 
		 * 3、若Son的构造方法中,如下:super("小明",8);		System.out.println("这是子类的无参构造方法");
		 * 			则先执行父类Father的有参构造方法,再执行子类Son的无参构造方法。
		 * 		【这是父类的有参构造方法
					这是子类的无参构造方法】
		 * 
		 * 总而言之,通过new 关键字为对象赋值,是通过调用构造方法来实现的。
		 */
		
	
		Father d1 = new Daughter();/*1、拓展:若子类有构造方法,向上造型,在调用子类的构造方法时,
		由于子类构造方法中第一行默认的super();默认			先		调用父类的构造方法。
		再执行子类构造方法中剩下的部分语句,向上造型完了之后,除非子类重写父类方法,
		否则其将没有自身的属性,换言之,子类拥有的都是父类的属性和方法
		 														2、【这是父类的无参构造方法】。为此题结果,向上造型,
		 														由于子类无构造方法,直接继承父类的构造方法为其赋值。
		 														*/
		Daughter d2 = new Daughter();/*【这是父类的无参构造方法】 调用子类的构造方法,
		因为子类没有构造方法,所以使用默认继承父类的构造方法为其赋值。*/
		/**
		 * ★★★以上两种创建对象的方式不同之处★★★
		 * 
		 * 语句1,d1拥有了父类的属性和方法,因为重写了一个父类的work方法,
		 * 没有完全丧失了自我。(★★Tip:编译时是父类的方法,执行的却是子类的)
		 * 
		 * 语句2,由于继承关系,不仅保持了自身的属性,还拥有了父类的属性和方法。
		 * 需要注意的是,就近原则,调用方法时,子类重写父类的方法会覆盖原父类的方法。
		 * 
		 */
	}
}


向上造型的意义:

为了以后写代码时拓展方便,以后万一还有别的子类,我们需要改的地方就少了。

个人学习笔记,若有误还望不吝赐教。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值