Java对象创建方式

父类代码和子类代码如下:

//父类
public class SuperClass {

    private String name;

    private static int age;

    {
        name = "hh";
        System.out.println("父类。。初始化实例块。。");
    }

    static {
        age = 18;
        System.out.println("父类。。初始化静态代码块。。");
    }

    public SuperClass(String name) {
        System.out.println("父类。。有参构造函数。。");
        this.name = name;
    }

    public SuperClass() {
        System.out.println("父类。。无参构造函数。。");
    }

    @Override
    public String toString() {
        return "SuperClass{" +
                "name='" + name + '\'' +
                "age" + age + '\'' +
                '}';
    }
}

//子类
public class SubClass extends SuperClass {
    private String company;

    private static String phone;

    {
        company = "wangwang";
        System.out.println("子类。。初始化实例块。。");
    }

    static {
        phone = "1888888888";
        System.out.println("子类。。初始化静态代码块。。");
    }

    public SubClass(String name, String company) {
        super(name);
        this.company = company;
        System.out.println("子类。。有参构造函数1。。");
    }

    public SubClass(String company) {
        this.company = company;
        System.out.println("子类。。有参构造函数2。。");
    }

    public SubClass() {
        System.out.println("子类。。无参构造函数。。");
    }

    @Override
    public String toString() {
        return super.toString() + "SubClass{" +
                "company='" + company + '\'' +
                "phone='" + phone + '\'' +
                '}';
    }
}
  1. 使用new关键字
SubClass subClass = new SubClass("Willow","niu");
  1. 使用Class类的newInstance方法(反射机制)

newInstance方法调用无参构造器创建对象

SubClass subClass = (SubClass) Class.forName("com.bean.SubClass").newInstance();
SubClass subClass = SubClass.class.newInstance();
  1. 使用Constructor类的newInstance方法(反射机制)

该方法和Class类中的newInstance方法很像,但Constructor类的newInstance可以调用有参数的和私有的构造函数

Constructor<SubClass> constructor = SubClass.class
                .getConstructor(String.class);
SubClass subClass = constructor.newInstance("Willow");
  1. 使用Clone

调用clone()方法时:1.对象必须继承Cloneable 2、必须重载clone方法。

//继承+override clone(),其他同上
public class SubClass extends SuperClass implements Cloneable {
   
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

//创建时调用
SubClass subClass = new SubClass("Willow","niu");
SubClass subClass2 = (SubClass) subClass.clone();
  1. 使用(反)序列化机制

当反序列化一个对象时,JVM会创建一个单独对象并且不会调用任何构造函数。为了反序列化一个对象,类必须实现Serializable接口。

父类实现Serializable接口

public class SuperClass implements Serializable

反序列化对象

public static void main(String[] args) throws Exception {
        SubClass subClass = new SubClass("Willow","Willow's company");
        ObjectOutputStream output = new ObjectOutputStream(
                new FileOutputStream("SubClass.txt"));
        output.writeObject(subClass);
        output.close();

        System.out.println(subClass);
        System.out.println("***********************");

        ObjectInputStream input = new ObjectInputStream(new FileInputStream(
                "SubClass.txt"));
        SubClass outSubClass = (SubClass) input.readObject();
        System.out.println(outSubClass);
        input.close();
    }

输出结果

javadialog如何设置父容器 java创建父类_jvm

类的加载顺序

虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块叫“类加载器”

类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件,在java中类装载器把一个类装入JVM,经过以下步骤:

  1. 加载:查找和导入Class文件
  2. 链接:其中解析步骤是可以选择的 (a)检查:检查载入的class文件数据的正确性 (b)准备:给类的静态变量分配存储空间
    (c)解析:将符号引用转成直接引用
  3. 初始化:对静态变量,静态代码块执行初始化工作
public class Demo1Application {
    public static void main(String[] args) throws Exception {
        SubClass subClass = new SubClass("Willow","niu");
        System.out.println(subClass);
    }
}

结果如下:

javadialog如何设置父容器 java创建父类_System_02


在类中,加载顺序为:
1.首先加载父类的静态字段或者静态语句块。
2.子类的静态字段或静态语句块。
3.父类普通变量以及语句块。
4.父类构造方法被加载。
5.子类变量或者语句块被加载。
6.子类构造方法被加载。
静态方法,调用的时候才会加载,不调用的时候不会加载。
静态语句块和静态变量被初始化的顺序与代码先后顺序有关。

JVM双亲委派模型

JVM双亲委派模型:如果一个类加载器收到类加载请求,它不会立刻加载这个类,而是将请求委派给父类加载器去加载该类,最终加载请求会打到引导类加载器,只有当父类加载器无法完成加载请求(也就是搜索范围内无该类),子加载器才会自己尝试去加载这个类。

javadialog如何设置父容器 java创建父类_System_03

为什么JVM的类加载要采用双亲委派模型加载类?

基于双亲委派模型设计,那么Java中基础的类,Object类似Object类重复多次的问题就不会存在了,因为经过层层传递,加载请求最终都会被Bootstrap ClassLoader所响应。加载的Object类也会只有一个,否则如果用户自己编写了一个java.lang.Object类,并把它放到了ClassPath中,会出现很多个Object类,这样Java类型体系中最最基础的行为都无法保证,应用程序也将一片混乱。

双亲委派模型的好处:
1.安全性,避免用户自己编写的类动态替换JAVA的一些核心类。
2.避免类的重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类。

JVM中表示两个class对象是否为同一个类对象存在两个必要条件:
1.类的全限定名必须一致,包括包名。
2.加载这个类的ClassLoader(指ClassLoader实例对象)必须相同。