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,由于继承关系,不仅保持了自身的属性,还拥有了父类的属性和方法。
* 需要注意的是,就近原则,调用方法时,子类重写父类的方法会覆盖原父类的方法。
*
*/
}
}
向上造型的意义:
为了以后写代码时拓展方便,以后万一还有别的子类,我们需要改的地方就少了。
个人学习笔记,若有误还望不吝赐教。