Java创建对象的方式,你知道几种?

145 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

1.Java对象生命周期

永远记住:Java创建对象的根本途径就是调用构造方式!!! ,但是调用构造方法不一定创建对象(子类创建对象会调用父类的构造方法,但是没有创建父类的对象)

一个Java类的完整生命周期,经历:1.加载 2.连接 3.初始化 4.使用 5.卸载

1.1 JVM内存区域

Java的核心机制:JVM(Java虚拟机-跨平台)和GC(垃圾自动回收机制)

内存区域的介绍:

(1)堆内存(Heap):用于存放类的对象实例(保存对象地址),共享

(2)栈内存(Stack):Java虚拟机栈,是由一个一个栈帧组成的**后进先出的栈式结构,栈帧中存放的是运行时产生局部变量、方法等信息。当调用一个方法的时候,虚拟机栈中就会创建一个栈帧存放这些数据的内存**,当方法调用完毕之后,栈帧消失。如果方法被其他方法调用,则**继续在栈帧顶部创建新的栈帧(尽量少使用递归调用)**

(3)方法区:Java中虚拟机中有一块区域(共享)存放已经**加载的类信息(创建Class对象):属性和方法**、常量、静态变量(全局数据区域、static修饰共享数据)以及方法代码的内存区域

(4)常量池:使用final关键字修饰的变量,常量池是方法区的一部分,主要是用来存放常量和李忠的符号引用等信息(java.lang.String

1.2 初始化

如果一个类被直接易用,就会触发类的初始化,在Java中,直接引用情况如下:(什么是虚引用

  • 通过new关键创建对象、读取或者设置类的静态变量、调用类的静态方法
  • 初始化子类的时候,会触发父类中的初始化(继承)
  • 作为程序入口直接运行的时候,也可以直接调用main方法

创建对象的时候,调用构造方法,会对成员变量(实例变量)进行初始化操作,静态变量的信息在类加载的时候就已经存放到方法区域中了。

1.3 卸载

在类使用之后,如果满足以下的情况,类就会被卸载(回收):

  • 该类所有的实例已经被GC(被回收),也就是Java的堆内存中不存储该类的任何实例
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象(类被加载就创建了Class对象,所有创建实例都是由同一个Class对象创建的),没有被任何地方引用的时候,无法在任何地方通过反射方位该类的方法。

2.Java创建对象的方式

(1)使用new关键字:最常用的方式,可以调用任意的构造方法(无参还是有参)

(2)使用Class类的newInstance方法创建对象,但是该方法只能调用无参数的构造方法

(3)通过反射获取构造方法对象(Constructor)使用newInstance,可以调用有参或者无参的所有的构造方法

(4)使用clone克隆方法:源对象,当我们使用clone的时候,JVM就会创建一个新对象,但是使用clone方法,不会调用任何的构造方法,类必须要实现Cloneable接口

(5)序列化:当我们使用序列化和反序列创建一个对象的时候,JVM会创建一个新的对象,反序列的时候不会调用任何构造方法,但是必须要实现java.io.Serializable

public class Test01 {
	public static void main(String[] args) throws Exception {
		Student s1 = new Student();
		System.out.println("s1 = " + s1);

		Student s2 = new Student("悟空");
		System.out.println("s2 = " + s2);


		Student s3 = Student.class.newInstance();
		System.out.println("s3 = " + s3);

		Class<Student> clazz = (Class<Student>) Class.forName("com.pangsir.model.Student");
		Student s4 = clazz.newInstance();
		System.out.println("s4 = " + s4);

		Constructor<Teacher> c1 = Teacher.class.getDeclaredConstructor();//获取无参数
		Teacher t1 = c1.newInstance();
		System.out.println("t1 = " + t1);

		Constructor<Teacher> c2 = Teacher.class.getDeclaredConstructor(String.class);
		c2.setAccessible(true);
		Teacher t2 = c2.newInstance("八戒");
		System.out.println("t2 = " + t2);
	}
}
public class 克隆 {
	public static void main(String[] args) throws Exception {
		Dog d1 = new Dog("小白");
		System.out.println("d1 = " + d1);
		System.out.println("d1.getName() = " + d1.getName());
		System.out.println("=============");
		Dog d2 = (Dog)d1.clone();
		System.out.println("d2 = " + d2);
		System.out.println("d2.getName() = " + d2.getName());
	}
}

public class 序列化 {
	public static void main(String[] args) throws Exception {
		Cat cat = new Cat();
		cat.setName("小白..."+ Math.random());

		OutputStream out = new FileOutputStream("D:/Cat.kk");
		ObjectOutputStream oos = new ObjectOutputStream(out);
		oos.writeObject(cat);//数据写入到Cat.kk文件
		oos.close();
	}
}

public class 反序列化 {
	public static void main(String[] args) throws Exception {
		InputStream in = new FileInputStream("D:/Cat.kk");
		ObjectInputStream ois = new ObjectInputStream(in);
		Cat cat = (Cat)ois.readObject();
		System.out.println("cat = " + cat);
	}
}

3.实例变量初始化

实例变量,在创建对象的时候,由构造进行初始化(也可以直接调用公开的setter方法,再次进行赋值)

public class Pig implements Serializable {
	public String name;

	public Pig(){
		System.out.println("Pig无参数");
	}
	public Pig(String name){
		System.out.println("Pig有参数");
		this.name=name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println(this.name+",已经在构造方法的时候赋值");
		this.name = name;
	}

	@Override
	public String toString() {
		return "Cat{" +
				"name='" + name + '\'' +
				'}';
	}
}
package com.pangsir.test;

import com.pangsir.model.Dog;
import com.pangsir.model.Pig;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class 实例变量初始化 {
	public static void main(String[] args) throws Exception {
		Pig p1 = new Pig();
		System.out.println("p1 = " + p1);
		System.out.println("================");
		Pig p2 = new Pig("小红");
		System.out.println("p2 = " + p2);

		System.out.println("================");
		Pig p3 = new Pig();
		p3.setName("小白");
		System.out.println("p3 = " + p3);

		System.out.println("================");
		Constructor<Pig> c1 = Pig.class.getDeclaredConstructor(String.class);
		c1.setAccessible(true);
		Pig p4 = c1.newInstance("小绿");
		System.out.println("p4 = " + p4);

		System.out.println("================");
		Field nameField = Pig.class.getDeclaredField("name");
		nameField.setAccessible(true);
		//重新赋值
		nameField.set(p4,"小黑");
		System.out.println("p4 = " + p4);


	}
}