关于抽象类与继承的几个问题
例一:
import java.lang.reflect.Field;
public class ReflectTest{
public static void main(String[] args) throws Exception{
Student student = new Student("Male", 26, "NO.14 Middle School");
student.dump();
System.out.println("This student's age is not be " + student.getAge());
student.setAge(16);
System.out.println("This student's age should be " + student.getAge());
student.dump();
}
}
class Student extends Person{
private String school;
Student(String sex, int age, String school){
super(sex, age);
this.school = school;
}
public void dump(){
System.out.println("This Student's info = {sex:" + sex + ", age:" + super.getAge() + ", school:" + school + "}");
}
}
abstract class Person {
public String sex;
private int age;
Person(String sex, int age){
this.sex = sex;
this.age = age;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
执行结果为:
This Student's info = {sex:Male, age:26, school:NO.14 Middle School}
This student's age is not be 26
This student's age should be 16
This Student's info = {sex:Male, age:16, school:NO.14 Middle School}
- 抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。
- 抽象类其实可以被实例化,但是它的实例化方式并不是通过普通的new方式来创建对象,二是通过父类的应用来指向来指向子类的实例间接的实现了父类的实例化,因为子类在实例化之前,一定会先实例化它的父类。这样创建了继承抽象类的子类对象,也就把其父类(抽象类)给实例化了。
- 子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法。
- 父类的private变量和方法也会被继承并初始化在子类父对象(super)中,只不过对外不可见。
Student student = new Student("Male", 26, "NO.14 Middle School");
这句话就是给Student实例对象分配堆空间。因为Student继承Person父类,所以虚拟机首先加载person类到方法区,并在堆中位父类成员变量在子类空间中初始化,然后加载Student类到方法区,为Student类的成员变量分配空间并初始化值。
本例中继承的内存分配图如下:
例二:
import java.lang.reflect.Field;
public class ReflectTest{
public static void main(String[] args) throws Exception{
Model model = new Model();
model.run();
model.sayHello();
}
}
class Model extends ParentModel{
public String welcome = "Hello world!";
public void run(){
super.run();
System.out.println("子类的欢迎语:" + welcome);
}
public void sayHello(){
super.sayHello();
System.out.println("我是子类......");
}
}
abstract class ParentModel {
public String welcome = "Hello java!";
public void run(){
System.out.println("父类的欢迎语:" + welcome);
}
public void sayHello(){
System.out.println("我是父类......");
}
}
- 子类中定义的成员变量和父类中定义的成员变量相同时,则父类中的成员变量不能被继承。
- 子类中定义的成员方法,并且这个方法的名字返回类型,以及参数个数和类型与父类的某个成员方法完全相同,则父类的成员方法不能被继承。
- 如果子类声明了跟父类一样的变量,那意味着子类将有两个相同名称的变量,一个存放在子类实例对象中,一个存放在父类子对象中。
本例中继承的内存分配图:
例三:
import java.lang.reflect.Field;
public class ReflectTest{
public static void main(String[] args) throws Exception{
Class parentModelClass = Model.class.getSuperclass();
Field field = parentModelClass.getDeclaredField("welcome");
Model model = new Model();
model.sayHello();
field.setAccessible(true);
field.set(model, "Hello world!");
model.sayHello();
}
}
class Model extends ParentModel{
public void sayHello(){
super.run();
}
}
abstract class ParentModel {
private String welcome = "Hello java!";
public void run(){
System.out.println(welcome);
}
}
执行结果为:
Hello java!
Hello world!
- java反射机制提供的setAccessible(true)方法可以取消java的权限控制检查。
- 通过反射可以修改父类对象(super)的私有属性。