1、试写出三种访问修饰符和各自访问属性权限
public --------本项目内
缺省的 --------本包内
private ---------本类内
2. 创建一个Person封装类,具有name、age、gender属性,并提供有参构造器
public class Person(){
private String name;
private int age;
private char gender;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public void setGender(char gender){
this.gender=gender;
}
public char getGender(){
return gender;
}
public Preson(String n,int a, char g){
name=n;
age=a;
gender=g;
}
public Person(){
}
3. 简述this关键字的用法和功能
this.内容
调用属性或者方法
在本类内,调用本对象的属性或者方法,直接写就可以,this是省略的
局部变量和成员变量是允许重名的,如果重名,就需要显示的写this区分成员变量
this()
调用本类的构造器
小括号内,构造器的实参列表
必须写在构造器的第一行
4.继承之成员变量内存图
4 ,阅读下面程序,思考他的输出结果,并解释(十分重要--顶级练习难度)
//(顶级练习)
public class Test {
public static void main(String[] args) {
So so = new So("tom");
//在调用这个method方法时,所有的空间都已经初始化了
so.method(20); //儿子--20
}
}
//父类
class Fa{
private String name = "父亲"; //tom
public Fa(String name){ //tom
this.name=name;
method(100); //this调用方法,看实际对象,new So()
//method 方法调用的是重写之后的
//父类的构造器在调用子类的方法!现在正在对父类空间进行初始化
//父类空间优于子类空间!此时子类空间初始化了吗?没有 ;所以子类空间还没有初始化,只是处在加载的时候,name也就没有被赋值为儿子
}
public void method(int a){
System.out.println(name+"--"+a);
}
}
//子类
class So extends Fa{
private String name="儿子"; //同名属性
public So(String name){ //tom
super(name); //调用父类的有参构造 tom
}
public void method(int a){ //重写方法
System.out.println(name+"--"+a); // null--100
}
}
输出结果: null--100
儿子--20
解释:
子类和父类中有属性重名的情况下this是什么:
① this调用属性 this.成员变量! 调用的是谁的,看类型 this的类型是谁,就看this在哪个类中! ② this 调用方法 this.成员方法 调用的是谁的,看实际对象 this的实际对象是谁,看new的是谁!
So so = new So("tom"); 父类空间优于子类空间,在执行到父类的构造器调用子类的方法时,先对父类的空间进行初始化,在重写方法输出的时候,子类中的name还没有被初始化,还处于加载时候的状态,为null值,故输出结果为null--100
so.method(20); 而在执行这条语句的时候,所有的空间都已经被初始化了,所以输出的结果是
儿子--20
下面给出程序执行的内存图:
5.解决一个疑惑:
原来学习的是this指代的是当前对象,今天又说this是谁要看是变量还是方法,简单说就是变量看类型,方法看对象(如果this.变量,则指代的是该所属类型中的变量;如果是this.方法,则指代的是所属对象中的方法)这不是与我们前面学习的矛盾吗?
不矛盾,首先我们原来所学的this指代的是对象是正确的。今天在这里所说的this指代是一种特殊情况下的,他是有前提的:子类和父类中出现了重名的属性。遵循下面的规则:
this调用属性 this.成员变量! 调用的是谁的,看类型 this的类型是谁,就看this在哪个类中! this 调用方法 this.成员方法 调用的是谁的,看实际对象 this的实际对象是谁,看new的是谁!
举个例子:
/*
继承之应用在成员变量
*/
public class Demo {
public static void main(String[] args) {
Son son=new Son();
//前提:有属性重名
son.method();//子类中的,name是子类的name
son.function();//父类继承下来的,name是父类的
Father father=new Son();//多态的写法
//father对象类型是? Father
//father对象实际是什么? Son
}
}
//父类
package com.atguigu.bean;
public class Father {
public String name="jack";
public int age;
public void function(){
//this不是当前对象?为什么是父类的name?
//成员变量的调用,看对象的类型,Father中的this是什么类型的对象?Father
System.out.println(name);//子类还是父类?
//this是当前对象!类型是Father,为什么调用的是子类的eat方法呢?
//成员方法在调用的时候,看对象的实际对象(new的是谁),this的实际对象Son
eat();//调用的是子类的还是父类的!调用的是子类的
//属性看类方法看对象
}
public void eat(){
System.out.println("Father在吃饭");
}
}
//子类
package com.atguigu.bean;
public class Son extends Father {
public String name="rose";
public void method(){
//this调用成员变量,看类型!Son类中的this的类型就是Son
//this在哪个类中,this的类型就是谁!
System.out.println(this.name);//子类的
this.eat();//是子类的eat方法!
}
public void eat(){
System.out.println("Son在吃饭");
}
}
在这个例子中,父类和子类中出现了重名的属性name;在执行son.method();语句时System.out.println(this.name);中的this在Son类,所以name是Son类中的值rose;在执行son.function();程序语句时,System.out.println(name);中的this(可省略)是属于Father类的name值jack。在强调一下,这是在属性重名的情况下,如果在子类中没有name这个属性,this就会向上寻找,找到父类中的name属性值输出。