*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同一时间允许多个线程进行访问,效率较高,但可能会出现并发错误