构造方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构造方法相关的知识,希望对你有一定的参考价值。

*java中没有构造函数的概念
构造方法是创建对象时调用的方法,不要理解为构造方法就是创建对象的方法,因为构造方法主要是用来加载和初始化类的一些资源,创建一个对象并不完全靠
构造方法完成,构造方法主要进行创建对象的收尾工作
构造方法的作用?
能够在创建对象的时候完成对属性的赋值
构造方法如下:
public class TestConstract1{
    public static void main(String[] args){
        Rect re = new Rect(45,32);
        re.showArea();
    }
}
class Rect{
    int length;
    int width;
    public Rect(int length, int width){
        this.length = length;
        this.width = width;
    }
    public void showArea(){
        System.out.println(length*width);
    }
}
java中只要是一个类,就一定有构造方法,即使程序员没有写,系统也会提供一个默认的构造方法,该方法无参且空体;
如果程序员写了自己的构造方法,那么系统就不再提供默认的构造方法,相当于中国的低保制度,没钱才领低保,有钱无论多少都不会领到低保

构造方法和普通方法的区别?
1:构造方法没有返回类型,连void都不能写
2:构造方法的名字需要和类名一模一样 -->构造方法名首字母大写

构造方法的首行默认是隐藏的super():
super():表示在执行本类构造方法之前,先去执行父类的构造方法
默认去找父类的无参构造方法:
public class TestConstract2{
    public static void main(String[] args){
        Son s = new Son();
    }
}
class GrandFather{
    public GrandFather(){
        //super()
        System.out.println("爷爷被创建出来了");
    }
}
class Father extends GrandFather{
    public Father(){
        //super()
        System.out.println("爸爸被创建出来了");
    }
}
class Son extends Father{
    public Son(){
        //super()
        System.out.println("儿子被创建出来了");
    }
}
打印的结果是:
爷爷被创建出来了
爸爸被创建出来了
儿子被创建出来了
--------------
在java中,GrandFather默认继承Object类,所以,在创建对象时也会执行super(),然后去执行Object类的构造方法
如果父类没有无参构造方法:
public class TestConstract3{
    public static void main(String[] args){
        Teacher tea = new Teacher("张三",29);
        System.out.println(tea.name);
    }
}
class Person{
    String name;
    int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    //public Person(){}
}
class Teacher extends Person{
    //String name; int age 从父类继承得到
    public Teacher(String name,int age){
        this.name = name;
        this.age = age;
    }
}
此段程序执行会报错,因为Teacher类中默认会执行super(),去找父类Person的无参构造方法,而父类中没有无参构造方法,所以会报错
两种方法解决:
1.提供父类的无参构造方法
2.在super里面传参数,指定找父类的哪一个构造方法

构造方法首行还可以出现this():

public class TestConstract4{
    炒鸡蛋 cc = new 炒鸡蛋("西红柿");
}
class 炒鸡蛋{
    public 炒鸡蛋(){
        System.out.println("热锅 放油");
        System.out.println("打蛋 搅拌 放入锅中");
        System.out.println("翻炒鸡蛋");
    }
    public 炒鸡蛋(String x){// x-->佐料
        this();
        System.out.println("放入" + x);
        System.out.println("继续翻炒鸡蛋");
    }
}
该段程序执行结果:
热锅 放油
打蛋 搅拌 放入锅中
翻炒鸡蛋
放入西红柿
继续翻炒鸡蛋

this():表示要执行本构造方法之前,先去执行本类的其他构造方法,具体执行哪个构造方法,看this()里面的参数类型

下面是默认super()以及成员变量和局部变量区别的例子
public class TestConstract5{
    public static void main(String[] args){
        //Demo d1 = new Demo();
        //System.out.println(d1.str); //打印,"能做对么"

        //Demo d2 = new Demo("etoak");
        //System.out.println(d2.str); //打印,null

        Sample s = new Sample("etoak");
        System.out.println(s.str);  //打印,"能做对么"
    }
}
class Demo{
    String str; //成员变量
    public Demo(){
        str = "能做对么?"; //成员变量 = "能做对么"
    }
    public Demo(String str){ //str:局部变量:etoak
        str = "还敢错么?"; //局部变量 = "还敢错么?"
    }//局部变量str消亡
}
class Sample extends Demo{
    //String str 继承得到成员变量str
    public Sample(String str){  //str局部变量 = etoak
        //super(); //成员变量 = 能做对么?
        str = "OK?" //局部变量 = OK?
    } //局部变量str消亡
}
下面是super调用父类有参构造方法实现代码共享的例子:
public class ExecConstract{
    public static void main(String[] args){
        Teacher tea = new Teacher("Tom",29,5000.0);
        System.out.println(tea.name);
    }
}
class Person{
    String name;
    int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
}
class Teacher extends Person{
    //name age
    double salary;
    public Teacher(string name,int age,double salary){
        super(name,age);
        this.salary = salary;
    }
}
*:构造方法的首行只能出现this()/super()中的一个
有super()就不能有this()
有this()就不能有super()
面试题:
1.构造方法能不能方法重载?
可以
2.构造方法能不能进行方法覆盖?
方法覆盖的前提:需要子类先继承得到
但是父类的构造方法子类不能继承,所以没办法进行方法覆盖

参数传递

    参数传递有两种说法,一种是java中只有值传递,另一种是java中的基本数据类型传值,引用数据类型传地址
public class TestArgs1{
    public static void main(String[] args){
        int a = 10;
        change(a);
        System.out.println(a); //打印结果:10
    }

    public static void change(int x){
        //int x = a; 隐含的一句代码
        x = 55;
    }
}
内存图:

技术分享

public class Testargs2{
    public static void main(String[] args){
        int a = 56;
        int b = 90;
        change(a,b);
        System.out.println(a); //56
        System.out.println(b); //90
    }
}
public static void change(int x , int y){
    //int x = a; int y = b;
    int z = x;
    x = y;
    y = z;
}//x, y, z是局部变量
内存图:

技术分享

public class TestArgs3{
    public static void main(String[] args){
        String str1 = new String("O");
        String str2 = new String("K");
        change(str1,str2);

        System.out.println(str1); //O
        System.out.println(str2); //K
    }
    public static void change(String x , String y){
        //String x = str1,String y = str2;
        String z = x;
        x = y;
        y = z;
    }//x,y,z是局部变量
}
java中,任何一个字符串底层都是char[]字符数组实现的
内存图:

技术分享

public class TestArgs4{
    public static void main(String[] args){
       Student x = new Student(30);
       change(x);
       System.out.println(x.age); //打印,55
    }

    public static void change(Student stu){
        //Student stu = x ;
        stu.age = 55;
    }
}
class Student{
    int age;
    public Student(int age){
        this.age = age;
    }
}
内存图:

技术分享

public class TestArgs5{
    public static void main(String[] args){
        Student x = new Student(30);
        change(x);
        System.out.println(x.age);  //打印,30
    }

    public static void change(Student stu){
        //Student stu = x;
        stu = new Student(55);
    }
}
class Student{
    int age;
    public Student(int age){
        this.age = age;
    }
}
内存图:

技术分享

String类的两个常见面试题:
1.new和不new之间的区别?
    String str1 = "etoak";
    String str2 = new String("etoak");
    不new方式涉及到常量池查找机制
public class TestString1{
    public static void main(String[] args){
        String str1 = "etoak";//执行时,先到常量池寻找是否有"etoak",有,则不用创建对象;没有,则开辟内存空间,创建"etoak"对象,并将其存入常量池
        String str2 = "etoak";//执行时,常量池中已经有"etoak",所以直接指向"etoak"
        System.out.println(str1 == str2);   //true

        String str3 = new String("etoak");
        String str4 = new String("etoak");
        System.out.println(str3 == str4);   //false
    }
}
2.String StringBuffer StringBuilder都表示字符串,它们三者之间的区别?
A:String和StringBuffer/StringBuilder之间的区别?
字符串的底层都是通过char[]字符数组实现的
String str = new String("etoak");
//[5]有5个字符,所以会开辟5个字符大小空间,当想要在其后再追加一个字符,则需要再申请开辟6个字符大小空间,并将etoak复制到新的空间,
以后每追加字符串都需要重新申请开辟空间并复制,效率较低
StringBuffer buffer = new StringBuffer("etoak");
//[5+16]有5个字符,因为StringBuffer/StringBuilder在创建对象时会预留16块缓冲区,
当不断字符串里面追加元素的时候,先使用缓冲区,缓冲区也装满之后,如果再追加n个字符,会申请开辟[21+n]*2大小的空间,以后再装满都按照这种机制扩充
当不断字符串里面追加元素的时候,尽量使用StringBuffer/StringBuilder
追加方法:buffer.append();
效率对比:
public class Speed{
    public static void main(String[] args){
        //String +=
        //StringBuffer append
        String str1 = new String();//""
        StringBuffer buffer = new StringBuffer();//""

        long time1 = System.currentTimeMillis();
        for(int x = 1; x <= 10000 ; x++){
            str1 += x;
        }
        long time2 = System.currentTimeMillis();
        System.out.println(time2 - time1);

        long time3 = System.currentTimeMillis();
        for(int x = 1; x <= 10000; x++){
            buffer.append(x);
        }
        long time4 = System.currentTimeMillis();
        System.out.println(time4 - time3);
    }
}
B:StringBuffer和StringBuilder的之间的区别?
    StringBuffer同一时间只允许一个线程进行访问,效率较低,但是不会出现并发错误
    StringBuilder同一时间允许多个线程进行访问,效率较高,但可能会出现并发错误

以上是关于构造方法的主要内容,如果未能解决你的问题,请参考以下文章

init()方法和构造方法的区别

构造方法和构造函数

java中的构造方法

java构造方法和方法的区别

构造方法与普通方法

类的构造方法