概况
据我所知,Java创建对象有以下几种方法:
- 使用new关键字
- 使用Class类的newInstance方法
- 使用Constructor类的newInstance方法
- 使用Clone的方法
- 使用反序列化
下面我们来一一练习。
获取类的位置和名称
package 获取类的位置和名称;
import pojo.Person;
public class GetClassName {
public static void main(String[] args) {
Class<?> demo2=null;
Class<?> demo3=null;
//方式1
demo2=new Person().getClass();
//方式2
demo3=Person.class;
System.out.println("类名称 "+demo2.getName());
System.out.println("类名称 "+demo3.getName());
}
}
Class类
package 无参数反射;
import pojo.Person;
public class TestClassNewInstance {
public static void main(String[] args) {
//想反射创建对象,首先我们需要知道类的位置和名称
//这句话获取类的包名和类名
String p=Person.class.getName();
System.out.println("对象的包名+类名:"+p);
Class<?> demo=null;
try{
demo=Class.forName(p);
/*
* 笔记:
* Class.forName(xxx.xx.xx) 返回的是一个类
* 作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
*
* 从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。
* 但是使用newInstance()方法的时候,就必须保证:
* 1、这个类已经加载;
* 2、这个类已经连接了。
* 而完成上面两个步骤的正是Class的静态方法forName()所完成的,
* 这个静态方法调用了启动类加载器,即加载java API的那个加载器。
*
*
* newInstance: 弱类型。低效率。
* new: 强类型。相对高效。能调用任何public构造。
*/
}catch (Exception e) {
e.printStackTrace();
}
Person per=null;
try {
//下面的“(Person)”可以换成demo实现的接口
per=(Person)demo.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
per.setName("周星驰");
per.setAge(20);
System.out.println(per);
}
}
package 有参数反射;
import java.lang.reflect.Constructor;
import pojo.User;
public class ClassNewInstance {
public static void main(String[] args) {
// 这句话获取类的包名和类名
String p = User.class.getName();
Class<?> demo = null;
try {
demo = Class.forName(p);
} catch (Exception e) {
e.printStackTrace();
}
User per0 = null;
User per1 = null;
User per2 = null;
User per3 = null;
User per4 = null;
// 取得全部的构造函数
Constructor<?> cons[] = demo.getConstructors();
System.out.println(cons.length);
try {
// 默认的构造函数的下标最大,User一个有五个构造函数,所以默认构造函数的下标为4
per0 = (User) cons[4].newInstance();
// 构造函数1
per1 = (User) cons[0].newInstance("Rollen");
// 构造函数2
per2 = (User) cons[1].newInstance(20);
// 构造函数3
per3 = (User) cons[2].newInstance("Rollen", "周星星");
// 构造函数4
per4 = (User) cons[3].newInstance("Rollen", 20, "周星星");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(per0);
System.out.println(per1);
System.out.println(per2);
System.out.println(per3);
System.out.println(per4);
}
}
Constructor类
package 有参数反射;
import java.lang.reflect.Constructor;
import pojo.User;
public class ConstructorNewInstance {
/*
* newInstance() 的参数版本与无参数版本详解
*
* 通过反射创建新的类示例,有两种方式: Class.newInstance() Constructor.newInstance()
*
* 以下对两种调用方式给以比较说明: Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
* Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
*
* Class.newInstance() 抛出所有由被调用构造函数抛出的异常。
*
* Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的;
* Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。
*/
public static void main(String[] args) {
String className = User.class.getName();
try {
/* 可以使用相对路径,同一个包中可以不用带包路径 */
Class<?> c = Class.forName(className);
/* 以下调用无参的、私有构造函数 */
Constructor<?> con1 = c.getDeclaredConstructor();
/*
* 笔记: 在类的外面获取此类的私有成员变量的value时 将此对象的 accessible 标志设置为指示的布尔值。 值为 true
* 则指示反射的对象在使用时应该取消 Java 语言访问检查。 值为 false 则指示反射的对象应该实施 Java 语言访问检查。
* 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问
*
*
* 如果有private修饰,默认accessible为false,则会报错
* java.lang.IllegalAccessException: Class
* 有参数反射.ConstructorNewInstance can not access a member of class
* pojo.User with modifiers "private"at
* sun.reflect.Reflection.ensureMemberAccess(Unknown Source)at
* java.lang.reflect.Constructor.newInstance(Unknown Source)at
* 有参数反射.ConstructorNewInstance.main(ConstructorNewInstance.java:42)
*/
con1.setAccessible(true);
User user01 = (User) con1.newInstance();
/* 以下调用带参的、私有构造函数 */
Constructor<?> con2 = c.getDeclaredConstructor(new Class[] {
String.class, String.class });
con2.setAccessible(true);
User user02 = (User) con2
.newInstance(new Object[] { "jevon", "李叔叔" });
System.out.println("调用无参的:" + user01);
System.out.println("调用带参的:" + user02);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Clone方法
Person p = new Person(23, "zhang");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
深入研究参考博客:http://blog.csdn.net/u011679955/article/details/52736379
反序列化
参考博客:
http://www.cnblogs.com/fuck1/p/5462052.html
http://blog.csdn.net/wangloveall/article/details/7992448/