构造函数
在构建创造对象时调用的函数。(只针对对象构造,无对象,不构造)
作用:
可以给对象进行初始化。创建对象都必须要通过构造函数初始化。
一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数,如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。
特点:
1.函数名与类名相同。(首字母大写)
2.不用定义返回值类型。
3.没有具体的返回值。
例如:
Person(String n,int a)
{
age=a;
name=n;
}
一般函数和构造函数有什么区别呢?
构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。
构造函数:对象创建后,会调用只调用一次。
一般函数:对象创建后,需要函数功能时才调用。
一般函数:对象创建后,可以被调用多次。
什么时候定义构造函数呢?
在描述事物时,该事物已存在就具备的一些内容,这些内容都定义在构造函数中。
一个类中可以有多个构造函数。(多个构造函数以重载的形式出现)
构造函数的内存图解
注意:
构造函数是要进栈的。调用一次后弹栈,初始化完毕。
Person p = new Person(“xiao”);
调用Person
首先会系统默认初始化
然后,构造函数的初始化再来一次
最后,自定义的构造函数再走一次
细节1:
Person(String n)
Public void Person(String n) //加上一个void就变成了方法
可以同时拥有
第一个是构造函数初始化,只能使用一次
第二个是方法 可以多次使用
细节2:
在方法中不可以调用构造函数,因为构造函数只针对对象,无对象,不构造
细节3:
构造函数前面加上void 变成一般函数 不再是构造函数
细节4:
构造函数中自动有return;语句
this关键字
Person(String name)
{
name=name;
}
当Person per = new Person(“旺财”); 定义一个对象结束后,其中的name属性的值还是null。因为以上的构造函数,进栈后,在栈中有一个name的局部变量,然后就自己给自己赋值。与堆里面的name属性无关,故name的值仍然是null。
正确做法是,用 this 表现是是对象的 name。
当成员变量和局部变量同名时,可以用this区分。this:代表当前对象。this就是所在函数所属对象的引用。this . name =>per.name。简单说,哪个对象调用了this所在的函数,this即代表该对象的引用。
public void speak()
{
System.out.println(this.name+":"+this.age);
}
Person(String name,int age)
{
this.age=age;
this.name=name;
}
以上都是有this的,加了this即引用当前对象。如果没有this时,如果堆内存没有这个变量,回到栈内存中找。
构造函数调用另一个重构的构造函数
Person(String name,int age)
{
this(name);
this.age=age;
}
Person(String name)
{
this.name=name;
}
其中的内存图解为:
以上为执行到程序person p = new Person(“旺财”,30);在调用构造函数时,执行以下语句时的内存图解。
this(name);—>this.name=name;
以上构造函数调用另一个构造函数时,有一个需要注意的点:this只能定义在构造函数的第一行。因为初始化动作要先执行。而且不能两个构造函数不能互相调用,有这样会形成递归,可能造成栈内存溢出。
Person(String name,int age)
{
this(name);
this.age=age;
}
这样是对的。
Person(String name,int age)
{
this.age=age;
this(name);
}
而这样是错的。
this的应用
只要类中用到本类的属性,就可以用this.属性表示。
static关键字(—实现数据共享)
static的特点
1 static是一个修饰符 用于修饰成员
2 static修饰的成员被所有对象所共享
3 static优先于对象存在 因为static成员随着类的加载就已经存在了
4 static修饰的成员多了一种调用方式 就可以直接被类名所调用(类名调用:person. name)
5 static修饰的数据是共享数据 对象中存储的是特有数据 被static修饰的变量称为静态变量或类变量
成员变量和静态变量(类变量)的区别?
1.两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2.调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类调用。
3.别名不同
成员变量也称为实例变量。
静态变量称为类变量。
4.数据存储位置不同。
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据.
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据.
静态使用的注意事项:
1,静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)(因为静态随着类存在而存在,而非静态成员随对象存在而存在,而类先存在,后存在对象,故静态方法无法访问非静态变量)
2,静态方法中不可以使用this或者super关键字。
3,主函数是静态的。 (只能调用静态的函数和变量,调用非静态的函数和变量可以用对象调用(创建一个对象来调用这个函数)。)
class Demo1
{
int num = 4;
public static void main(String[] args)
{
new Demo1() .show(); //匿名对象
}
public void show()
{
System.out.println(num);
}
}
主函数(main函数)解析
主函数特殊之处:
1.格式是固定的。
2.被JVM识别和调用。
public static void main(String[] args)
public:因为权限必须是最大的。
static:不需要对象的,直接用主函数所属类名调用即可。
void:主函数没有具体的返回值。
main:函数名,不是关键字,只是一个jvm识别的固定的名字。
String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
注意:
1、(String[] args)是main的参数列表,可以给主函数传参数,一般不传参数啦,所以一般为null。
2、main函数的格式是固定的,public static void main(String[] args) ,其中可变的是args,即参数名。
static关键字的内存图解
注意:
1、左上为栈,右上为堆,下面为方法区(数据共享区)。
2、在方法区中左边为非静态方法区,右边为静态方法区。
3、在方法区中都是函数(方法)的代码。以便调用。调用时进栈,调用完毕则出栈。
静态什么时候用?
1.静态变量
a) 当分析对象中所具备的成员变量都相同时,这时这个成员可以被静态修饰。
b) 只要这个数据在对象中是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。
c) 如果是相同的数据,对象不需要修改,只需要使用即可,不需要存储在对象中,定义成静态的。
2.静态函数
a) 函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。
简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能 就是非静态的。
如果不需要,就可以将该功能定义成静态的。
但是非静态需要被对象调用 而仅创建对象调用非静态的没有访问特有数据的方法 该对象的创建是没有意义的
静态代码块
随着类的加载而执行 而且只执行一次
作用:用于给类进行初始化
class StaticCodeDemo
{
static
{
System.out.println("a");
}
public static void main(String[] args) {
System.out.println("aaa");
}
}
//这个时候会先输出a 在输出aaa 因为静态代码块随着类的创建而执行
一般用类静态代码块初始化的类中全都是静态成员。
class Demo2
{
static int num ;
static
{
num = 10;
System.out.println("huahd");
}
}
构造代码块
class Demo1
{
public static void main(String[] args)
{
Person p1 = new Person();
}
public void show()
}
class Person
{
private String name;
{ // 构造代码块,可以给所有对象进行初始化的。与对象有关,凡是定义一个类的对象,就执行一次。
System.out.println("new Person");
}
Person() // 构造函数,给对应的对象进行针对的初始化,可能会有构造重构Person(name)等。
{
name = "baby";
cry();
}
public void cry()
{
System.out.println("哇哇");
}
} //结果为 new Person
//哇哇
在函数中的{ }为局部代码块,在类里面的为构造代码块,类中前加static{}的代码块为静态代码块。面试中问,那个代码块先执行,一般是静态代码块限制性,因为随着类的存在而加载,若有对象就是构造代码块,若函数则局部代码块。