java创建对象的几种方式

java中创建对象有几种方式?

使用new关键字

如 User user=new User();

执行这条语句,jvm做了什么?

1. 首先在方法区的常量池中查看是否有new 后面参数(也就是类名)的符号引用,并检查是否有类的加载信息也就是是否被加载解析和初始化过。如果已经加载过了就不在加载,否则执行类的加载全过程
2. 加载完类后,大致做了如下三件事:
    a、给实例分配内存
    b、调用构造函数,初始化成员字段
    c、user对象指向分配的内存空间
    注意:new操作不是原子操作,b和c的顺序可能会调换?

使用clone方法

当我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。因为Object 类的 clone 方法的 原理是从内存中(堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那构造函数没有被执行也是非常正常的了.

使用clone方法创建对象的实例:


public class CloneTest implements Cloneable{

    private String name; 

    private int age;

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public CloneTest(String name, int age) {

        super();

        this.name = name;

        this.age = age;

    }

    public static void main(String[] args) {

        try {

            CloneTest cloneTest = new CloneTest("酸辣汤",18);//todo

            CloneTest copyClone = (CloneTest) cloneTest.clone();

            System.out.println("newclone:"+cloneTest.getName());

            System.out.println("copyClone:"+copyClone.getName());

        } catch (CloneNotSupportedException e) {

            e.printStackTrace();

        }

    }

}

输出:

newclone:酸辣汤

copyClone:酸辣汤

注意:
1.clone是Object中的方法,Cloneable是一个标识接口,它表明这个类的对象是可以拷贝的。如果没有实现Cloneable接口却调用了clone()函数将抛出异常

2.Object.clone()未做同步处理,线程不安全

3.clone()有深拷贝和浅拷贝两种方式

使用反序列化

序列化是干什么的?

简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自 己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。一句话概括:序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。

java中要序列化的类必要实现Serializable接口

什么情况下需要序列化

a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;

b)当你想用套接字在网络上传送对象的时候;

c)当你想通过RMI(远程方法调用)传输对象的时候;

使用反序列化创建对象实例:

1.对象要实现Serializable接口


import java.io.Serializable; 

public class Person implements Serializable { 

    int age; 

    int height; 

    String name; 

    public Person(String name, int age, int height){ 

        this.name = name; 

        this.age = age; 

        this.height = height; 

    } 

}

2、序列化与反序列化


import java.io.FileInputStream; 

import java.io.FileOutputStream; 

import java.io.IOException; 

import java.io.ObjectInputStream; 

import java.io.ObjectOutputStream; 

public class MyTestSer { 

/**

* Java对象的序列化与反序列化

*/ 

public static void main(String[] args) { 

  Person zhangsan = new Person("zhangsan", 30, 170); 

  Person lisi = new Person("lisi", 35, 175); 

  Person wangwu = new Person("wangwu", 28, 178); 

  try { 

      //需要一个文件输出流和对象输出流;文件输出流用于将字节输出到文件,对象输出流用于将对象输出为字节 

      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser")); 

      out.writeObject(zhangsan); 

      out.writeObject(lisi); 

      out.writeObject(wangwu); 

  } catch (IOException e) { 

e.printStackTrace(); 

  } 

  try { 

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser")); 

      Person one = (Person) in.readObject(); 

      Person two = (Person) in.readObject(); 

      Person three = (Person) in.readObject(); 

      System.out.println("name:"+one.name + " age:"+one.age + " height:"+one.height); 

      System.out.println("name:"+two.name + " age:"+two.age + " height:"+two.height); 

      System.out.println("name:"+three.name + " age:"+three.age + " height:"+three.height); 

  } catch (Exception e) { 

e.printStackTrace(); 

  } 

  } 

}

运行结果:

name:zhangsan age:30 height:170  //todo

name:lisi age:35 height:175 

name:wangwu age:28 height:178

android中的场景

1.组件间(如activity间)的对象传递 (实现Parcelable或Serializable接口)

2.使用 Binder进行进程间的通讯传递的对象必须实现Parcelable接口

Serializable 是java的序列化接口,使用简单但是开销比较大,序列化和反序列化都涉及到大量的I/O操作,效率相对较低。Parcelable是Android提供的序列化方法,更适用于Android平台,效率很高,但是使用起来比较麻烦.Parcelable主要用在内存序列化上,序列化存储设备或将序列化后的对象通过网络传输建议使用Serializable。

使用反射

通过反射来创建类对象的实例,有两个步骤:

  1. 首先我们得拿到类对象的Class

    如何获取? 有三种方式(反射章节会详细讲解)

    • 类.class,如Person.class
    • 对象.getClass()
    • Class.forName("类全路径")
  1. 通过反射创建类对象的实例对象

在拿到类对象的Class后,就可以通过Java的反射机制来创建类对象的实例对象了,主要分为两种方式:

  • Class.newInstance()

  • 调用类对象的构造方法

举个栗子:

首先准备一个Person的类:


public class Person {

    private String name;

    private int age;

    public Person() {

    }

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", age=" + age +

                '}';

    }

}

使用Class.newInstance()创建对象:

public class ClassNewInstance {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException {

        Person person = Person.class.newInstance();

        person.setAge(18);

        person.setName("酸辣汤");

        System.out.println(person);

    }

}

运行结果:

Person{name='酸辣汤', age=18}

注意 :newInstance创建对象实例的时候会调用无参的构造函数,所以必需确保类中有无参数的可见的构造函数,否则将会抛出异常。

调用类对象的构造方法——Constructor

Constructor是Java反射机制中的构造函数对象,获取该对象的方法有以下几种:

  • Class.getConstructors():获取类对象的所有可见的构造函数

  • Class.getConstructor(Class... paramTypes):获取指定的构造函数

获取类对象所有的构造方法并遍历:


public class ConstructorInstance {

    public static void main(String[] args) {

        Class p = Person.class;

        for(Constructor constructor : p.getConstructors()){

            System.out.println(constructor);

        }

    }

}

运行结果:

public com.eft.reflect.Person()

public com.eft.reflect.Person(java.lang.String,int)

获取指定的构造方法

通过Class.getConstructor(Class... paramTypes)即可获取类对象指定的构造方法,其中paramTypes为参数类型的Class可变参数,当不传paramTypes时,获取的构造方法即为默认的构造方法。


public class ConstructorInstance {

    public static void main(String[] args) throws Exception {

        Class p = Person.class;

        Constructor constructor1 = p.getConstructor();//获取默认的构造方法

        Constructor constructor2 = p.getConstructor(String.class,int.class);//获取指定的构造方法

        System.out.println(constructor1);

        System.out.println(constructor2);

    }

}

运行结果:

public com.eft.reflect.Person()

public com.eft.reflect.Person(java.lang.String,int)

通过构造方法创建对象

Constructor对象中有一个方法newInstance(Object ... initargs),这里的initargs即为要传给构造方法的参数,如Person(String,int),通过其对应的Constructor实例,调用newInstance方法并传入相应的参数,即可通过Person(String,int)来创建类对象的实例对象。

测试代码如下:


public class ConstructorInstance {

    public static void main(String[] args) throws Exception {

        Class p = Person.class;

        Constructor constructor = p.getConstructor(String.class,int.class);

        Person person = (Person) constructor.newInstance("酸辣汤",18);

        System.out.println(person); 

    }

}

运行结果:

Person{name='酸辣汤', age=18}

如上通过反射创建对象,只是反射机制中的冰山一角,接下来详细介绍反射相关知识

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容