一、实现反射的三种方式
1.类 .getClass()
首先在object超类中有个public final Class<?> getClass()
,final意味着此方法不能被重写,所有类的实例化对象都可以调用。缺点:这种方式使用率较低,因为必须首先实例化对象才能调用这个方法。
2.包.类.class
不需要指定操作类的实例化对象,直接通过类名称就可以完成,比如java .util.Date.class hibernate 及mybatic。缺点:这种方式必须明确结构,即类必须存在,不是特别灵活。
3.Class.forName(类名称)
在Class类中有public static Class<?> forName(String className) throws ClassNotFoundException
方法。在工厂类设计模式有用到及jdbc加载驱动的时候。这种方式相对比较灵活,没有很强的严谨性,操作的类可以不存在,不会出现语法错误,但是运行时,必须设置指定的类。
二、反射实例化的方式
在获取Class类对象之后,才能操作实例化对象的方法。public T newInstance() throws InstantiationException, IllegalAccessException
异常信息解释:InstantiationException:无法实例化。原因:没有无参构造方法或者类名称错误
IllegalAccessException:错误的访问,构造方法私有化
因此,newstance() 只能调用类中的无参构造方法,相当于new一个实例化对象。两者区别不大,反射灵活性更高。若想实例化有参构造,可以调用构造函数,下面内容会解决这个问题。
三、反射的核心成员
java.lang.reflect包中有三大核心类:java.lang.reflect.Constructor<T>
,java.lang.reflect.Method,java.lang.reflect.Field
1.构造函数 java.lang.reflect.Constructor<T>
获取全部构造方法:public Constructor<?>[] getConstructors() throws SecurityException
获取指定构造方法:public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
获取构造方法名称:public String getName()
获取修饰符:public int getModifiers()
,注意这返回的是int类型的数字,所有修饰符都是通过数字编号取得的,比如1对应public,用 toString()方法可以进行还原操作。
获取参数类型:public Class<?>[] getParameterTypes()
获取构造方法上的全部异常信息:public Class<?>[] getParameterTypes()
下面是有参构造的实例化方法,不推荐使用有参的实例,相对复杂,必须提供全参。一般构造简单的无参的java类实例化
class Person{
private String name;
private Integer age;
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Demo {
public static void main(String args[]) throws Exception {
Class<?> demoClass = Class.forName("com.qiuyiliang.Person");
Constructor<?> personCst = demoClass.getConstructor(String.class,Integer.class);
Person person = (Person)personCst.newInstance("秋意凉",100);
System.out.println(person);
}
}
2.java.lang.reflect.Method
获取所有方法:public Method[] getDeclaredMethods()throws SecurityException
//此方法不包括继承的方法,只是本类中所有的方法
获取所有方法:public Method[] getMethods() throws SecurityException
//获取所有方法 包括继承来的
获取返回值类型:public Class<?> getReturnType()
调用本类的方法:public Object invoke(Object obj,Object... args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
注意:必须保证已经存在本类的实例化对象,而很方便的是这种实例化对象可以使用Object来代替,可以直接利用Class类反射实例化对象,而后通过Objcect对象操作,没有必要向下转型操作。原则上简单的java类中的属性一定要经过封装,编写setter getter方法。通过setter的方法设置属性的值。
操作method的代码(有参构造,有返回值,有参数):
class Person{
private String name;
private Integer age;
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String running(String str) {
System.out.println(str);
return str;
}
public class Demo {
public static void main(String args[]) throws Exception {
Class<?> demoClass = Class.forName("com.qiuyiliang.Person");
Constructor<?> constc = demoClass.getConstructor(String.class,Integer.class);
Object object = constc.newInstance("秋意凉",100);
Method method = demoClass.getMethod("running", String.class);
Object val = method.invoke(object, "running...");
System.out.println(val);
}
}
3 . java.lang.reflect.Field(属性成员)
获取成员:public Field[] getFields() throws SecurityException //获取全部包括继承的。但无法获取私有的属性
获取成员:public Field[] getDeclaredFields() throws SecurityException //获取全部本类的申明的属性,不包括继承的
获取某一个属性:public Field getField(String name) throws NoSuchFieldException, SecurityException
获取某一个属性:public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException 同理
获取属性的类型:public Class
class Person{
private String name;
private Integer age;
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String running(String str) {
System.out.println(str);
return str;
}
}
public class Demo {
public static void main(String args[]) throws Exception {
Class<?> demoClass = Class.forName("com.qiuyiliang.Person");
Constructor<?> constc = demoClass.getConstructor(String.class,Integer.class);
Field declaredField = demoClass.getDeclaredField("name");
Object object = constc.newInstance("秋意凉",100);
Method setMethod = demoClass.getMethod("setName", declaredField.getType()); //此处可灵活处理 “set”+declaredField.getName()
Method getMethod = demoClass.getMethod("getName"); //此处可灵活处理 “get”+declaredField.getName()
setMethod.invoke(object, "秋意凉2");
Object getObj = getMethod.invoke(object);
System.out.println(getObj);
}
}
四、反射的应用 :(待续…)