相关推荐recommended
Java中构造器详解(类的五成员之三:构造器)
作者:mmseoamin日期:2024-02-03

目录

  • 友情提醒
  • 概述:Java类的五成员之三:构造器
  • 一、构造器概述
    • 1)什么是构造器
    • 2)构造器特点(和普通方法的区别)
    • 3)构造器的重载(方法重载)
    • 4)执行构造方法之前
    • 二、this和super
      • 1)构造器中的this关键字
      • 2)构造器中的super关键字

        友情提醒

        先看文章目录,大致了解知识点结构,直接点击文章目录可以跳转到文章指定位置。

        概述:Java类的五成员之三:构造器

        Java的基本单位是类,类中包含五个部分,这篇写的是构造器。

        (1)变量

        (2)方法

        (3)构造器

        (4)初始化块

        (5)内部类

        一、构造器概述

        1)什么是构造器

        ①构造器是处于Java类中的一个方法,最大的作用创建对象时执行初始化。

        2)构造器特点(和普通方法的区别)

        ①构造方法名不能自定义必须和类名相同。普通的方法首字母小写后续单词字母大写。

        ②构造器可以哟访问权限修饰符但是不能有final,,static,,abstract,synchronized,native修饰符。

        ②没有返回值和返回类型,也不需要void。

        ③构造器在创建对象时执行初始化

        class Citizen 
        {	//成员属性
        	String name;
        	MyDate birth;
        	//构造方法
        	public Citizen(String n,MyDate b){
        		name = n;
        		birth = b;
        	}
        }
        

        3)构造器的重载(方法重载)

        ①缺省构造器指没有人为写构造方法时,系统隐式生成的空参构造器,当我们初始化对象不给对象的属性赋值时将调用此缺省构造方法。

        ②非缺省构造器指人为显示定义的构造方法,当我们初始化对象需要给对象的属性赋值时将调用此非缺省构造方法,当我们写了有参构造的时候,系统将不会再生成空参构造器必须我们手动写出来(显示定义)。

        ③二者构成重载现象

        class Citizen 
        {	//成员属性
        	String name;
        	MyDate birth;
        	//构造方法
        	public Citizen(String name,MyDate birth){
        		this.name = name;
        		this.birth = birth;
        	}
        	public Citizen(){
        	//空参构造,与有参构造构成了方法重载
        	}
        }
        

        4)执行构造方法之前

        在执行构造函数中的代码之前,先要执行隐式三步:

        a)super():调用父类构造函数

        b)给对象空间中的非静态成员变量显示赋值

        c)执行构造代码块

        创建对象的过程中执行优先级:

        静态代码块和静态成员变量执行顺序和代码中出现的顺序有关,静态成员变量优先于非静态成员变量,非静态成员变量优先于构造代码块,构造代码块优先于构造函数之前初始化

        也就是:

        静态代码块=静态成员变量>非静态成员变量>构造代码块>构造函数中代码

        构造函数结束出栈,对象创建完成。

        二、this和super

        1)构造器中的this关键字

        this用法

        ①this在构造器中,代表当前构造器正在创建的对象的内存地址,同时使用this在构造方法内部调用本类重载的构造方法必须只能在首行位置进行调用 否则将导致编译错误

        class Teacher
        {	String name;
            int age;
            //两个参数构造方法
            public Teacher(String name,int age){
           //this.name = name; //this. 的方式,如果没注释就得报错,因为this(name)必须首行
                this(name);			  //this(name);	 调用重载构造方法的方式
                this.age = age;
            }
            //一个参数构造方法
            public Teacher(String name){
                this(); // this();	 //调用重载构造方法的方式
                this.name = name;   //this. 不用放首行
                System.out.println("一个参数构造...this=" + this);		//②		同一个正在被创建对象的地址
            }
            //无参构造
            public Teacher(){
        //如果this("徐老师",32,);取消注释,会错误: 递归构造器调用,构造方法之间相互调用不能形成闭合回路
                //this("徐老师",32,);
                System.out.println("空参数构造...this=" + this);		//①		正在被创建对象的地址
            }
            public void printInfo(){
                System.out.println("姓名:" + name + ",年龄:" + age + ",籍贯:" + 
                address + "...this=" + this);//③	已经创建完成对象的地址
            }
        }
        

        ②this在非静态方法中:this代表已经创建完成的对象,指向正在执行方法的类的实例。(谁调用我,我指向谁)

        package test_this;
        class Person
        {   String name;
            int age;
            public Person(String n,int a){
                //① 此处的this记录的是当前正在被创建Person对象的内存地址
                System.out.println("构造方法...this=" + this);
                name = n;
                age = a;
            }
            public Person(){ }
            public void printInfo(){
                System.out.println("姓名:" + name + ",年龄:" + age + "...this=" + this);		//③ 此处this记录的是已经创建完毕Person对象的内存地址
            }
            public static void main(String[] args)
            {
                Person p = new Person("张三",30);
                System.out.println(p);		//② 此处的p记录的是已经创建完毕Person对象的内存地址
                p.printInfo();
            }
        }
        /*打印结果
        构造方法...this=test_this.Person@3d8c7aca
        test_this.Person@3d8c7aca
        姓名:张三,年龄:30...this=test_this.Person@3d8c7aca
        */
        

        ③用来区分成员变量和局部变量。

        class Student
        {   String name;
            private int age;
            char sex;
            public Student(String name,int age,char sex){
                this.name = name;
                this.age = age;
                this.sex = sex;
            }
            public Student(){ }
            public int getAge(){
                return this.age;
            }
            public void setAge(int age){
                this.age = age;
            }
            public void printInfo(){
                String name = "lili";
                int age = 18;
                System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",性别:" + this.sex);
            }
            public static void main(String[] args)
            {	String name = "lili";
                int age = 18;
                Student s = new Student("韩梅梅",19,'女');
                s.printInfo();
            }
        }
        // 打印结果 姓名:韩梅梅,年龄:19,性别:女
        

        ④静态方法不能使用this关键字,因为静态方法不属于类的实例,所以this也就没有什么东西去指向。

        2)构造器中的super关键字

        super关键字用法:

        ①super在普通方法中:用这个关键字去执行被重载的超类中的非静态方法,使用super.func()去调用超类中被重载的方法。

        ps:重写父类方法的时候可以在子类方法体里直接super.父类方法,直接把父类方法拿过来用然后再添加其他代码,达到复用的目的。

        class Father
        {	public void func(){
                System.out.println("Father...func");
            }
        }
        //---------------------------------分割--------------------------------
        class Son extends Father
        {	public void func(){
                System.out.println("Son...func");
            }
            public void test(){
                //func();
                super.func();
            }
        }
        

        ②super关键字在构造方法:子类构造方法首行隐式的有super()用来接受父类成员变量,先调用父类构造再调用子类构造。 对super的调用必须是构造器中的第一个语句。this() 和 super() 不能同时存在,因为他们都要写在构造函数的第一行。

        class Person
        {
            //属性
            String name;
            int age;
            public Person(String name,int age){
                this.name = name;
                this.age = age;
            }
            public Person(){ }
        }
        //------------------分割--------------------------------------
        class Worker extends Person
        {
        	//方式一:显示定义在构造方法内部调用super(...)构造
        	public Worker(String name,int age){
        		super(name,age);
        	}
        	//方式二:在Person类中有空参构造,本类的空参构造隐式的有super();
        	 public Worker(){
        	    //super();//可以不写
            }
        }
        

        ③父类和接口中如果都定义了相同名字的默认方法,子类继承父类的同时实现了该接口,默认执行父类中的方法,这是类优先原则,如果想使用接口中的方法:接口名.super.方法名。

        ④两个接口中都定义了相同名字的默认方法,子类同时实现两个接口,这时候编译器报错,需要选择一下具体用哪个,或者用接口名.super.方法名来选择,再或者直接全部重写。

        public interface Inter2 {
        	//默认方法1
        	public default void method(){
        		System.out.println("Inter2...method");
        	}
        	//默认方法2
        	public default void func(){
        		System.out.println("Inter2...func");
        	};
        	//抽象方法
        	void show();
        }
        //-------------------------------分割------------------------------
        public interface Inter3 {
        	//默认方法1
        	public default void method(){
        		System.out.println("Inter3...method");
        	}
        	//默认方法2
        	public default void func(){
        		System.out.println("Inter2...func");
        	};
        	//抽象方法
        	void show();
        }
        //-------------------------------分割------------------------------
        /*	接口冲突问题:
         * 	多个接口内部都定义了相同名字的默认方法,类同时去实现这多个接口,
         * 用接口名.super.方法名来选择,再或者直接全部重写。
         */
        public class InterImpl2 implements Inter2, Inter3 {
        	@Override//重写默认方法
        	public void method() {
        //		Inter2.super.method();
        //		Inter3.super.method();
        		System.out.println("都不适合,完全重写...");
        	}
        	@Override//重写默认方法
        	public void func() {
        		Inter2.super.func();
        	//	Inter3.super.func();
        	//	System.out.println("都不适合,完全重写...");
        	}
        	@Override//重写抽象方法
        	public void show() {
        		System.out.println("sbsbsb");
        	}
        }