Class对象的生成方式
1.Class.forName("类名字符串") (注意:类名字符串必须是全称,包名+类名)
2.类名.class
3.实例对象.getClass()
Class.forName、实例对象.class(属性)、实例对象getClass()的区别:
1)Class cl=A.class; JVM将使用类A的类装载器,将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象
2)Class cl=对象引用o.getClass();返回引用o运行时真正所指的对象(因为:儿子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象
3)Class.forName("类名"); JAVA人都知道.装入类A,并做类的初始化
附:
从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用Class对象的newInstance()方法的时候,就必须保证:1、这个 类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载 java API的那个加载器。
现在可以看出,Class对象的newInstance()(这种用法和Java中的工厂模式有着异曲同工之妙)实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。
最后用最简单的描述来区分new关键字和newInstance()方法的区别:
newInstance: 弱类型。低效率。只能调用无参构造。
new: 强类型。相对高效。能调用任何public构造。
实例对象的创建四种方式
public class CreateObj implements Cloneable,Serializable{
private static String filename = CreateObj.class.getResource("").getPath()+ "/obj.txt";
static File file = new File(filename);
static {
if (!file.exists())
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
// 1.第一种常用方式 (用new语句创建对象)
CreateObj s1 = new CreateObj();
System.out.println(s1);
// 2.第二种方式 静态方式 java.lang.InstantiationException (运用反射手段)
CreateObj s2 = (CreateObj) Class.forName( "com.newland.commons.collectionutil.CreateObj").newInstance();
System.out.println(s2);
//第三种方式 用对象流来实现 前提是对象必须实现 Serializable (运用反序列化手段)
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
new FileOutputStream(filename));
objectOutputStream.writeObject(s2);
ObjectInput input=new ObjectInputStream(new FileInputStream(filename));
CreateObj s3 = (CreateObj) input.readObject();
System.out.println(s3);
//第四种 必须 实现Cloneable接口 否则抛出CloneNotSupportedException(调用对象的clone()方法)
CreateObj obj=new CreateObj();
CreateObj s4= (CreateObj) obj.clone();
System.out.println(s4);
}
}
Class对象和实例对象的区别与联系:
任何 Java 的类或接口都是 Class 类的一个实例,反射就是 Java 自我管理这些(类、对象)的机制
Class对象的作用(应用):
1、可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器
Class cls =obj.getClass();
Field[] fields =cls.getDeclaredFields(); //获取该类的所有属性
for(Field field : fields){
field.getType(); //属性类型
field.getName(); //属性名称
}
Method[] methods = cls.getDeclaredMethods();//获取该类的所有方法
for(Method method : methods){
method.getReturnType(); //方法类型
method.getName(); //方法名称
}
Constructor[] constructors = cls.getDeclaredConstructors();//获取该类的所有构造器
for(Constructor constructor : constructors){
constructor .getName(); //构造器名称
}
2、可以创建对象并访问任意对象方法和属性等
Class<Date> date=Class.forName("类文件名"); //加载指定的类文件,获得一个Class对象
Date d=date.newInstance(); //由Class对象获得一个新实例对象(默认调用类的无参构造器)
public Object getFieldValue(Object obj , String fieldname){
Class cls = obj.getClass(); //反射出类型
Field field = cls.getDeclaredField(fieldname); //反射出类型属性
Object val =field.get(obj); //在对象obj上读取field属性的值
return val;
}
在对象obj上调用方法签名是(method ,paramTypes)的方法,params是传递的参数,有方法返回,无返回null
public Object getMethod(Object obj , String method , Class[] paramTypes , Object[] params){
Class cls = obj.getClass(); //反射出类型
Method m= cls.getDeclaredMethod(method , paramTypes); //反射出类型方法
Object val =m.invoke(obj , params); //在对象obj上调用方法m,传递参数类别params
return val;
}