什么是反射
在正常的类的使用中,一般是先确定类,然后使用new关键字产生实例化对象然后使用。如果想通过对象取得类的信息,那么可以使用Object类中的getClass()方法。
反射机制的初步操作如下:
1 | package Test1; |
运行结果:1
class java.util.Date
Class类对象实例化的三种方式
- getClass() 使用此类必须要有实例化对象
- 类.class 不需要实例化对象
- 调用Class类提供的方法:public static Class<?> forName(String className) throws ClassNotFoundException
反射实例化对象
实例化Class对象后,就可以利用Class类来进行类的反射控制,Class类的常用方法如下:
- public static Class<?> forName(String className) throws ClassNotFoundException 通过字符串设置类名称实例化Class对象
- public Class<?>[] getInterface() 取得类实现的所有接口
- public String getName() 取得反射操作类全名
- public String getSimpleName() 取得反射操作类名,不包括包名
- public Package getPackage() 取得反射操作类所在的包
- public Class<? super T> getSuperclass() 取得反射操作类的父亲
- public boolean isEnum() 反射操作类是否是枚举
- public boolean isInterface() 反射操作类是否是接口
- public boolean isArray() 反射操作类是否是数组
- public T newInstance() throws 反射实例化对象
通过newStance()方法,可以实例化Class类包装的类型,不使用关键字new也可以进行对象的实例化操作。
注:使用newStance()方法进行实例化,类中一定要有无参构造方法,否则会出错
利用反射实例化对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package Test1;
class Book{
public Book() {
System.out.println("这是无参构造");
}
public String toString() {
return "hello";
}
}
public class testDemo19 {
public static void main(String args[]) throws Exception{
Class<?> cls=Class.forName("Test1.Book");
("deprecation")
Object obj=cls.newInstance();
Book book=(Book) obj;
System.out.println(book);
}
}
本程序通过实例化Class类,然后利用newStance()方法进行类包装的对象的实例化,实例化的对象是Object类,需要向下转型强制变为子类。
反射调用构造
使用newStance()方法实例化对象,必须要求类里面存在无参构造方法,如果类中没有无参构造方法的话,就必须通过java.lang.reflect.Constructor类来实现对象的反射实例化操作。
java.lang.Class取得构造方法的操作如下:
- public Constructor<?>[] getConstructors() throws SecurityException 取得全部的构造方法
- public Constructor
getConstructor(Class<?> parameterTypes) throws 取得指定类型的构造方法
Java.lang.reflect.Constructor类常用的操作方法如下:
- public Class<?>[] getExceptionTypes() 取得构造方法上所有抛出异常的类型
- public int getNodifiers() 取得构造方法上的修饰符
- public String getName() 取得构造方法的名字
- public getParameterCount() 取得构造方法中的参数的个数
- public Class<?>[]getParameterTypes() 取得构造方法中的参数类型
- public T newInstance(Object…initargs) 调用指定参数的构造实例化对象
明确调用勒种有参构造1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package Test2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Book{
private String title;
private int price;
public Book(String title,int price) {
this.title=title;
this.price=price;
}
public String toString() {
return "名字:"+this.title+",价格:"+this.price;
}
}
public class testDemo1 {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> cls=Class.forName("Test2.Book");
Constructor<?> con=cls.getConstructor(String.class,int.class);
Object obj=con.newInstance("中国上下五千年",199);
System.out.println(obj);
}
}
反射调用方法
常用“对象.方法()”调用方法,利用反射机制也可以实现类方法的操作
Class类取得方法的操作:
- public Methode[] getMethod() throws SecurityException 取得类中全部的方法
- public Method getMethod(String name,Class<?> parameterTypes) throws 取得类中指定名称与参数类型的方法
Method常用方法如下:
- public int getModifiers() 取得方法的修饰符
- public Class<?> getReturnType() 取得方法的返回值类型
- public int getParameterCount() 取得方法中定义的参数数量
- public Class<?>[] getParameterTypes() 取得方法定义中参数类型
- public Object invoke(Object obj,Object…args) throws Exception 反射调用方法并执行方法中所需要的参数
- public Class<?>[] getExceptionTypes() 取得方法抛出的异常类型
使用反射类操作java类属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package Test2;
import java.lang.reflect.Method;
class Book2{
private String title;
public void setTitle(String title) {
this.title=title;
}
public String getTitle() {
return title;
}
}
public class testDemo2 {
@SuppressWarnings("deprecation")
public static void main(String args[]) throws Exception{
String fieldName="title";
Class<?> cls=Class.forName("Test2.Book2");
Object obj=cls.newInstance();
Method setMet=cls.getMethod("set"+initcap(fieldName), String.class);
Method getMet=cls.getMethod("get"+initcap(fieldName));
setMet.invoke(obj, "Java开发");
System.out.println(getMet.invoke(obj));
}
public static String initcap(String str) {
return str.substring(0,1).toUpperCase()+str.substring(1);
}
}
反射调用成员
除了构造方法,普通方法,反射类也可以进行成员的操作,Class类中成员的取得方法如下:
- public Field[] getDeclaredFields() throws SecurityException 取得本类定义的全部成员
- public Field getDeclaredFields(String name) throws… 取得本类指定名称成员
- public Field[] getFields() throws SecurityException 取得本类继承父类的全部成员
- public Field getFields(String name) throws… 取得本类继承父类中指定的成员
Field类常用描述成员信息的方法如下:
- public Class<?> getType() 取得该成员的类型
- public Object get(Object obj) throws… 取得指定对象中的成员内容
- public void set(Object obj,Object value) throws… 设置指定对象中成员内容,相当于直接利用对象调用成员设置内容
利用反射类操作私有成员:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package Test2;
import java.lang.reflect.Field;
class Book3{
private String title;
}
public class testDem03 {
public static void main(String args[]) throws Exception{
Class<?> cls=Class.forName("Test2.Book3");
@SuppressWarnings("deprecation")
Object obj=cls.newInstance();
Field titField=cls.getDeclaredField("title");
titField.setAccessible(true);
titField.set(obj, "Java开发");
System.out.println(titField.get(obj));
}
}
