1、Class对象的获取有三种方式:
(1)任何类的对象可以通过调用Object类提供的**getClass()取得该类Class对象;
(2)类名称.class可以直接根据某个具体类来取得其Class对象
(3)调用Class类的静态方法Class.forName(String className)**传入类的全名称来取得其Class对象
且任何一个类的Class对象由JVM加载后产生(该Class对象在JVM中全局唯一)
public class Test1 {
public static void main(String[] args) {
/*根据类正向产生对象*/
Date date=new Date();
System.out.println(date);
/*
* 反射
* */
//1.类对象.getClass
System.out.println(date.getClass());
//2.类名称.class
System.out.println(Date.class);
//3.Class.forName(String className)
try {
System.out.println(Class.forName("java.util.Date"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
/*任何一个类的class对象有且只有一个*/
System.out.println(date.getClass()==Date.class);//true
try {
System.out.println(date.getClass()==Class.forName("java.util.Date"));//true
System.out.println(Class.forName("java.util.Date")==Date.class);//true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、根据反射取得一个类的Class对象后,可以通过反射来实例化对象,在Class类中有如下方法:
(1) public T newInstance() throws InstantiationException, IllegalAccessException
这种方法只能调用无参构造,并且无参构造必须是public权限;
方法是: 类对象.newInstance();
public class CreateObject {
public static void main(String[] args) throws Exception {
/*1.获取类的Class对象*/
Class<?> cls=Class.forName("java.util.Date");
/*2.通过反射取得Date的实例化对象*/
Date date=cls.newInstance();
System.out.println(date);
}
}
(2)还有一种是Constructor类提供的实例化对象的方法:
public T newInstance(Object … initargs)
方法是:在使用newInstance之前,要先获取构造方法Constructor,再对象.newInstance(…);括号内是要赋予对象属性的值;
而要获取本类中有参构造方法的方式有:
public Constructor getDeclaredConstructor(Class<?>… parameterTypes)
或者 public Constructor getConstructor(Class<?>… parameterTypes)
class Parent {
private String name;
private Integer age;
public Parent(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Parent{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class CreateObject2 {
public static void main(String[] args) {
Class<?> cls = Parent.class;
/*获取构造方法*/
try {
//如果类中的构造方法是私有的,getDeclaredConstructor能够拿到该构造方法,但是不能实例化对象
//要传入获取特定构造方法中的属性的class对象
Constructor constructor = cls.getDeclaredConstructor(String.class, Integer.class);
Parent parent = (Parent) constructor.newInstance("张三", 14);//传入实例化的属性值
System.out.println(parent);
} catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
3.根据反射可以获取类的方法
取得类中指定名称的普通方法
public Method getMethod(String name, Class<?>… parameterTypes)
public Method getDeclaredMethod(String name, Class<?>… parameterTypes)
既要传名称又要传类型,是因为:方法有重载;
取得类中全部普通方法
public Method[] getMethods() throws SecurityException
:取得本类以及父类中所有public方法,
public Method[] getDeclaredMethods() throws SecurityException
:取得本类中所有全部普通方法,包含私有方法;
Method类中提供调用类中普通方法的API:
public Object invoke(Object obj, Object… args) 传入实例化对象和获取到的方法的参数值
//先获取类对象
Class<?> cls= Per.class;
/*创建实例化对象*/
Per per= (Per) cls.newInstance();
/*拿到这个类中的setName的方法,传入方法的名称,如果该方法有参数,还要传入参数的类型*/
Method method= cls.getMethod("setName", String.class);
/*通过invoke进行调用,invoke方法内要传入创建好的实例化对象,如果该方法有参数再传入要赋予该对象的值*/
method.invoke(per,"李四");