常见的有4种方式
public class Person{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {}
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;
}
}
1.使用new关键字创建对象
public void testNew(){
Person person = new Person();
System.out.println(person);
}
2.利用反射
(1) 使用java.lang.Class
public void testClass() throws Exception{
Class clazz = Class.forName("cn.hbuas.object.Person");
Person person = (Person) clazz.newInstance();
System.out.println(person);
}
(2)使用java.lang.reflect.Constructor
public void testConstructor() throws Exception{
Constructor<Person> constructor = Person.class.getConstructor(String.class,int.class);
Person person = constructor.newInstance("Tom",20);
System.out.println(person);
}
第一种Class的newInstance方法内部调用的就是Construtor的newInstance
3.使用克隆
克隆主要分为浅克隆和深克隆
>浅克隆:如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,就是在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制
>深克隆:无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象
>浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制
这里只简单的介绍浅克隆
要求:(1) 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
(2) 覆盖clone()方法,把访问修饰符设为public,方法中调用super.clone()方法得到需要的复制对象
修改Person类
public class Person implements Cloneable{
private String name;
private int age;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
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 void testClone() throws CloneNotSupportedException{
Person person = new Person();//原Person
Person clone = (Person) person.clone();//克隆的Person
System.out.println(person);
System.out.println(clone);
}
4.利用反序列化创建对象
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。然后通过反序列化从流里将其读出来,可以实现对象的复制。
需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作,而且必须声明并赋值serialVersionUID字段,否则反序列化可能出错。
修改Person类
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
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 void testSerializable() throws IOException, ClassNotFoundException {
Person person = new Person();
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(person);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Object object = ois.readObject();
System.out.println(object);
}
java中除了上面4种常见的方式外,还有一个平时用的非常多的String类,String比较特殊
String s1 = "abc";
String s2 = new String("abc");
字符串直接赋值给String,也会隐含的创建String对象,如果s1改变,就会创建新对象,比如拼接字符串