构造函数
- 简单说,构造函数就是构建创造对象时调用的函数
- 创建对象都必须要通过构造函数初始化,一个类如果没有定义过构造过程,会有一个默认空参构造函数。若定义了指定的构造函数,那么类中默认构造函数就会消失。
特点
- 函数名与类类名相同
- 不能返回值类型
- 没有具体返回值
区别
- 构造函数- 对象创建时,会掉用与之相应的构造函数,对对象进行初始化
- 对象创建时,会调用且仅调用一次
 
- 一般函数- 对象创建后,需要使用函数功能时才调用
- 对象创建后,可调用多次
 
重载
- 当一个类中出现多个构造函数时,必须以重载形式体现
内存图解
- 接下来用下面这段代码,来演示内存变化过程1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16public class Person { 
 private String name;
 private int age;
 Person(){};
 Person(String name,int age){
 this.name = name;
 this.age = age;
 }
 public void speak(){
 System.out.println(name+":"+age);
 }
 public static void main(String[] args){
 Person person = new Person("jack",20);
 person.speak();
 }
 }

- 左面是栈内存,右面是堆内存。首先在栈内存运行main函数,创建名字为p的对象,然后栈内存调用了有参构造函数。在堆内存中开辟一片区域,给予其地址,将构造函数中的值寻址赋给堆中变量的值,然后将构造函数弹栈。将堆内存中的地址赋给p。

- 然后在栈中入栈speak方法,运行后寻址输出变量值this关键字
- 当成员变量和局部变量重名,可用关键字this区分
- this代表对象,一般当前对象,this代表其所在函数所属对象的引用1 
 2
 3
 4
 5
 6
 7
 8class Person { 
 Person(String name){
 this.name = name;
 }
 public static void main(){
 Person p = new Person(name);
 }
 }
功能
- this也可用于在构造函数中调用其他构造函数
- 注:只能定义在构造函数第一行,因为初始化动作要先执行 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- class Person { 
 Person(){}
 Person(String name){
 this.name = name;
 }
 Person(String name,int age) {
 this(name);
 this.age = age;
 }
 }
- 当执行主函数中的语句时,调用有参构造函数,此时this.name就是代指对象p 
- 简单来说,哪个对象调用this所在的函数,this就代表哪个对象注意事项
- 运行下面的代码失败,死循环1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13class Person { 
 Person(){
 this(jack);
 }
 Person(String name){
 this();
 this.name = name;
 }
 Person(String name,int age) {
 this(name);
 this.age = age;
 }
 }
内存图解
- 接下来通过下面的代码来演示更加完整的过程1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19public class Person { 
 private String name;
 private int age;
 Person(String name){
 this.name = name;
 }
 public void speak(){
 System.out.println(name+":"+age);
 }
 }
 public class test {
 public static void main(String[] args){
 Person p = new Person("rose");
 p.speak();
 Person p1 = new Person("dell");
 p1.speak();
 }
 }


- 首先在栈内存运行main函数,创建名字为p的对象,然后栈内存调用了有参构造函数。在堆内存中开辟一片区域,给予其地址后初始化数值,构造函数中的this起到了作用,指向p对象的地址,将 name=”jack” 传到堆中更改值,然后将构造函数弹栈。将堆内存中的地址赋给p。speak函数入栈也是通过this寻址堆中赋值。
小练习(双人年龄比较)
- 思路:在Person类中写一个boolean类型方法,巧妙地利用this就可以compare方法中只带一个参数。 - 1 
 2
 3- public boolean compare(Person p){ 
 return this.age == p.age ;
 }
- 主类中如何使用? - 1 
 2
 3- Person p1 = new Person(); 
 Person p2 = new Person();
 p1.compare(p2);
static关键字
特点
- static是一个修饰符,用来修饰成员
- static修饰成员被所有对象共享
- static优先于对象存在(static随类的加载就已经存在了)
- static修饰的成员多了一种调用格式,可以直接被类名调用。如:类名.静态成员
- static修饰的是共享数据 对象中存储的是特有数据成员变量、静态变量区别
- 区别:- 生命周期不同
- 调用方式不同
- 别名不同
- 数据存储位置不同
 
- 成员变量:- 随对象创建存在,随其回收而释放
- 只能被对象调用
- 实例变量
- 存在堆内存的对象中,也叫对象的特有数据
 
- 静态变量:- 随着类加载而存在,随着类消失而消失
- 可以对象调用,也可以类调用
- 类变量
- 存放在方法区(也叫共享数据区)的静态区中,也叫对象的共享数据
 
静态使用注意
- 静态方法只能调用静态成员(非静态都可以访问)
- 静态方法不可使用this 或者 super关键字
- 主函数静态的
内存图解
- 内存划分- 寄存器
- 本地方法区
- 方法区
- 栈内存
- 堆内存
 
- 接下来用一段代码来演示内存变化过程1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24public class Person { 
 private String name;
 private int age;
 static String country = "CN";
 Person(){};
 Person(String name,int age){
 this.name = name;
 this.age = age ;
 }
 public void show(){
 System.out.println(Person.country+":"+this.name+":"+this.age);
 }
 public static void method(){
 System.out.println(Person.country);
 }
 }
 public class test {
 public static void main(String[] args){
 Person.method();
 Person p = new Person("jack",20);
 p.show();
 }
 }

- 运行程序的时候,读取StaticDemo类,在方法区存放他的名字,注意还有他的自带的构造函数,然后在他的静态区粘贴上类的名字和代码,栈内存中压栈main,根据上面代码需要调用Person类,将Person类的构造函数show方法粘在方法区,在静态区添加入静态变量和静态方法。栈内存中压栈method,弹栈。继续执行主函数的语句,创建对象在堆内存开辟空间,压栈Person的构造函数,用this指向堆中的地址,赋值给堆内存。Person构造函数弹栈,将堆中地址赋值给p对象,show方法压栈,this指向堆中的地址,弹栈
静态什么时候用
静态变量
- 当分析对象中所具备的成员变量的值都是相同的,这是这个成员就可以被静态修饰。只要数据在对象中都不同的,就是对象的特有数据,必须存在对象中。非静态的若是有相同数据,且对象不需做修改只需要使用,,那么就不需要存储在对象中,定义成静态的就可以了
静态函数
- 参考一点,该函数功能是否有访问到对象中的特有数据
- 简单来说,从源代码看该函数功能是否需要访问非静态的成员变量,如果需要,该方法就是非静态的,如果不需要,该方法就可以定义成静态的
- 非静态需要被对象调用,而仅创建调用非静态但没有访问特有数据的方法,那么该对象的创建是没有意义的。
静态代码块
- 随类的加载而执行,且只执行一次
- 作用:给类初始化
- 构造代码块:给所有对象初始化
- 构造函数:给对应对象针对性初始化
- 执行顺序,谁先执行- 有对象:静态代码块 > 构造代码块 > 构造函数
- 无对象:静态代码块 > 构造函数 > 构造代码块
 
主函数特殊处
- 格式固定
- 被JVM所识别,所调用
- 分析:- public 权限最大
- static 不需要对象,直接用主函数所属类名调用
- void 没有具体返回值
- main 不是关键字,只是被JVM所识别固定的名字
- String[] args 主函数参数列表,一个数组类型参数,元素都是字符串
 
- 接下来我们输出代码测试一下 - 1 
 2
 3
 4- public static void main(String[] args){ 
 System.out.println(args);
 System.out.println(args.length);
 }
- 结果:[Ljava.lang.String;@1540e19d 0