构造函数

在构建创造对象时调用的函数。(只针对对象构造,无对象,不构造)

作用:

可以给对象进行初始化。创建对象都必须要通过构造函数初始化。
一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数,如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。

特点:

1.函数名与类名相同。(首字母大写)
2.不用定义返回值类型。
3.没有具体的返回值。
例如:

Person(String n,int a)
	{
		age=a;
		name=n;
	}

一般函数和构造函数有什么区别呢?

构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。
构造函数:对象创建后,会调用只调用一次。
一般函数:对象创建后,需要函数功能时才调用。
一般函数:对象创建后,可以被调用多次。

什么时候定义构造函数呢?

在描述事物时,该事物已存在就具备的一些内容,这些内容都定义在构造函数中。
一个类中可以有多个构造函数。(多个构造函数以重载的形式出现)

构造函数的内存图解

java构造函数中给数组初始化 java构造函数初始化对象_非静态


注意:

构造函数是要进栈的。调用一次后弹栈,初始化完毕。

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;
	}

其中的内存图解为:

java构造函数中给数组初始化 java构造函数初始化对象_非静态_02


以上为执行到程序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关键字的内存图解

java构造函数中给数组初始化 java构造函数初始化对象_初始化_03


注意:

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{}的代码块为静态代码块。面试中问,那个代码块先执行,一般是静态代码块限制性,因为随着类的存在而加载,若有对象就是构造代码块,若函数则局部代码块。