前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、Supper

1.1、父类

public class Father {

	public Father(){
		System.out.println("Father  constructor");
	}

	public Father(String str){
		System.out.println("Father   Param constructor "+ str);
	}

	public void otheMethod(){
		System.out.println("Father Method");
	}
}


1.2、子类


public class Son extends Father {

	/**
	 * 一、无参构造器
	 *  1、写不写  	super(); 都会调用父类中的无参构造器
	 */

	public Son(){
		super();
		System.out.println( "Son  constructor");
		System.out.println("---------------------");
		//死循环 还会调用父类
		Son son = new Son();
	}

	/**
	 * 二、有参构造器
	 1、下面 写super() 和   super(str) 会调用父类中对应的构造器
	 2、不写 suppr时候,像无参构造器那样自动执行 父类中supper()
	 */

	public Son(String str){
		// 1、什么都不写会主动调用父类中的 supper()
		// 2、super(str); 会调用父类中的有参构造器 ,不会调用无参构造器
		super(str);
		System.out.println( "Son  param constructor");
		System.out.println("---------------------");
	}



	/**
	 * 三、不是构造器的方法
	 1、 super() 等 相同类型 只能用在构造器中
	 2、super.父类方法  可以放在任意方法的任意位置
	 */

	@Override
	public void otheMethod(){
		//super.otheMethod();
		System.out.println("Son  Test Son");
		//super.otheMethod();
		System.out.println("---------------------");
	}


}

执行测试

public class D02_SuperMain {

	@Test
	public  void testSupperFatherConstrustor() {
		Son son = new Son();
		Father father = new Son();
	}

	@Test
	public void testSupperFatherParamConstrustor() throws Exception {
		String str  = "HealerJean";
		Father fatherParam = new Son(str);

	}

	@Test
	public void testOtherMethod() {
		Father fatherParam = new Son();
		fatherParam.otheMethod();
	}

}

2、static

2.1、对于静态字段,只有直接定义这个类的字段的类才会被加载

解释:很明显没有输出子类SubClass中的static代码块的信息,对于静态字段,只有直接定义这个类的字段的类才会被加载。

//1、父类
public class SuperClass {
    static{
        System.out.println("super class init!");
    }
    public static int a = 1;
    public final static int b = 1;
}


//2、子类
public class SubClass extends SuperClass{
    static{
        System.out.println("SubClass init!");
    }
}


//3、测试
public class Test {

    static{
        System.out.println("test class init!");
    }

    public static void main(String[] args){
        System.out.println(SubClass.a);
    }
}


test class init!
super class init!
1

2.2、当初始化类的时候,如果他的父类还没有被初始化,则需要先初始化它的父类

//1、父类
public class SuperClass {
    static{
        System.out.println("super class init!");
    }
    public static int a = 1;
    public final static int b = 1;
}

//子类
public class SubClass extends SuperClass{
    static{
        System.out.println("SubClass init!");
    }

    public static int s = 2; //对于静态字段,只有指定定义这个字段的类才会初始化
}

public class Test {

    static{
        System.out.println("test class init!");
    }

    public static void main(String[] args){
        System.out.println(SubClass.s);
    }
}


控制台
test class init!
super class init!
SubClass init!
2

2.3、讲static变成final

public final static int s = 2; //   

变成final常亮的时则不会初始化任何,因为它放到了常亮池中,并不是在类中获取的,所以不需要初始化,控制台只会打印出2

//1、父类
public class SuperClass {
    static{
        System.out.println("super class init!");
    }
    public static int a = 1;
    public final static int b = 1;
}

//子类
public class SubClass extends SuperClass{
    static{
        System.out.println("SubClass init!");
    }

    public final static int s = 2; 
}

public class Test {

    static{
        System.out.println("test class init!");
    }

    public static void main(String[] args){
        System.out.println(SubClass.s);
    }
}

控制台
test class init!
2

3、子类变量不和父类变量重复

  • 子类继承自父类的变量,其实是相当于复制了一个副本,不会改变父类自身变量的值

3.1、父类

@Data
public class Father {

    public String name = "父亲";

    public String printName() {
        return this.name;
    }

    public String printGetName() {
        return this.getName();
    }
}

3.2、子类

@Data
public class Son extends Father{


    @Override
    public String printName() {
        return this.name;
    }
    @Override
    public String printGetName() {
        return this.getName();
    }
}

执行测试

/**
     * 子类继承自父类的变量,其实是相当于复制了一个副本
     */
    @Test
    public void test1(){
        Father father = new Son();
        log.info("father.name:【{}】", father.name);
        //  父亲
        log.info("father.printName:【{}】", father.printName());
        //  父亲
        log.info("father.printGetName:【{}】", father.printGetName());
        //  父亲
        log.info("--------");


        father.name = "father = name";
        log.info("father.name:【{}】", father.name);
        //  【father = name】
        log.info(" ((Son) father).name:【{}】", ((Son) father).name);
        //  【father = name】
        log.info("father.getName:【{}】", father.getName());
        //  【father = name】
        log.info("father.printName:【{}】", father.printName());
        //  【father = name】
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【father = name】
        log.info("--------");

		//子类中虽然有方法,但是没有变量,所以方法调用的还是父类的
        father.setName("father set name");
        log.info("father.name:【{}】", father.name);
        //  【father set name】
        log.info("father.name:【{}】", ((Son) father).name);
        //  【father set name】
        log.info("father.getName:【{}】", father.getName());
        //  【father set name】
        log.info("father.printName:【{}】", father.printName());
        //  【father set name】
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【father set name】
        log.info("--------");




        Son son = new Son();
        son.name = "son == name" ;

        //子类强制转化为父类
        father = son;
        log.info("father.name:【{}】", father.name);
        //  【父亲】
        log.info("father.name:【{}】", ((Son) father).name);
        //  【son == name】
        log.info("father.getName:【{}】", father.getName());
        //  【son == name】
        log.info("father.printName:【{}】", father.printName());
        //  【son == name】
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【son == name】
        log.info("--------");


    }

4、子类变量和父类变量名字相同

  • 子类中声明了和父类名称一样的变量,则子类中对自己声明的变量的修改,不影响父类中变量的值

  • 变量赋值

    • **变量直接赋值(=)(son.name father.name),改变的自己的变量值或者是父类的变量值, **

    • 如果setName,肯定是看被实例化的对象是谁,那就给自己赋值啊,因为调用的方法肯定是自己内部的。

4.1、父类

@Data
public class Father {

    public String name = "父亲";

    public String printName() {
        return this.name;
    }

    public String printGetName() {
        return this.getName();
    }
}

4.2、子类

@Data
public class Son extends Father{

    public String name = "儿子";

    @Override
    public String printName() {
        return this.name;
    }
    @Override
    public String printGetName() {
        return this.getName();
    }
}

执行测试

    /**
     *  1、子类中声明了和父类名称一样的变量,则子类中对自己声明的变量的修改,不影响父类中改变量的值
     *  2、 变量直接赋值(=)(son.name   father.name),改变的自己的变量值或者是父类的变量值,
     *     如果setName,肯定是看被实例化的对象是谁,那就给自己赋值啊,因为调用的方法肯定是自己内部的。
     */
    @Test
    public void test2() {

        Father father = new Son();
        log.info("father.name:【{}】", father.name);
        //  【父亲】 (这个变量是父类的)
        log.info("father.printName:【{}】", father.printName());
        //  【儿子】 (方法是子类的)
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【儿子】 (方法是子类的)
        log.info("--------");


        //1、父类中有变量名,所以改变的是父类中的变量
        father.name = "father = name";
        log.info("father.name:【{}】", father.name);
        //  【father = name】     //父类中的属性
        log.info(" ((Son) father).name:【{}】", ((Son) father).name);
        //  【儿子】 (强制转化成了子类,因为子类中有该属性,所以打印的是子类的变量的值)
        log.info("father.getName:【{}】", father.getName());
        //  【儿子】(方法是子类的)
        log.info("father.printName:【{}】", father.printName());
        //  【儿子】(方法是子类的)
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【儿子】(方法是子类的)
        log.info("--------");

        
        //2、子类中有方法且有变量,所以 调用的是子类的方法,子类的name值改变了,父类没有改变
        father.setName("father set name");
        log.info("father.name:【{}】", father.name);
        //  【father = name】    子类中声明了和父类名称一样的变量,则子类中对自己声明的变量的修改,不影响父类中变量的值
        log.info("father.name:【{}】", ((Son) father).name);
        //  【father set name】 (强制转化成了子类,因为子类中有该属性,所以打印的是子类的变量的值)
        log.info("father.getName:【{}】", father.getName());
        //  【father set name】
        log.info("father.printName:【{}】", father.printName());
        //  【father set name】
        log.info("father.printGetName:【{}】", father.printGetName());
        //  【father set name】
        log.info("--------");

    }

ContactAuthor