程序可以访问、检测和修改它本身状态或行为的一种能力。
反射在Java中的体现就是一组反射类Reflection API
1) Object.getClass()
如果你有一个对象,那么可以调用这个对象的getClass()方法。
Class c = "foo".getClass();
Set<String> s = new HashSet<String>();
Class c = s.getClass();
2).class语法
如果你有一个类,但是没有这个类的实例,那么可以用类名.class来获取。
Class c = boolean.class;
Class c = int[][][].class;
Class c = java.io.PrintStream.class;
包装类型用.TYPE
Class c = Double.TYPE;
3)Class.forName()
如果你有一个类的全路径,可以通过Class类的静态方法Class.forName()获取。
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
包括
待检测的类
@MyAnnotation(value = "学生类")
public class Student<T> extends People implements Serializable {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 父类
public class People {
}
// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
}
public class Demo {
public static void main(String... args) {
try {
Class<?> c = Class.forName("lesson10.Student"); // 类路径
System.out.format("类名 Class:%n %s%n%n", c.getCanonicalName()); // 类名
System.out.format("修饰符 Modifiers:%n %s%n%n",
Modifier.toString(c.getModifiers())); // 修饰符
System.out.format("泛型参数 Type Parameters:%n");// 泛型参数
TypeVariable[] tv = c.getTypeParameters();
if (tv.length != 0) {
System.out.format(" ");
for (TypeVariable t : tv)
System.out.format("%s ", t.getName());
System.out.format("%n%n");
} else {
System.out.format(" -- No Type Parameters --%n%n");
}
System.out.format("接口 Implemented Interfaces:%n"); // 接口
Type[] intfs = c.getGenericInterfaces();
if (intfs.length != 0) {
for (Type intf : intfs)
System.out.format(" %s%n", intf.toString());
System.out.format("%n");
} else {
System.out.format(" -- No Implemented Interfaces --%n%n");
}
System.out.format("继承路径 Inheritance Path:%n"); // 继承路径 父类->父类的父类...
List<Class> l = new ArrayList<Class>();
printAncestor(c, l);
if (l.size() != 0) {
for (Class<?> cl : l)
System.out.format(" %s%n", cl.getCanonicalName());
System.out.format("%n");
} else {
System.out.format(" -- No Super Classes --%n%n");
}
System.out.format("注解 Annotations:%n"); // 注解
Annotation[] ann = c.getAnnotations();
if (ann.length != 0) {
for (Annotation a : ann)
System.out.format(" %s%n", a.toString());
System.out.format("%n");
} else {
System.out.format(" -- No Annotations --%n%n");
}
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
private static void printAncestor(Class<?> c, List<Class> l) {
Class<?> ancestor = c.getSuperclass();
if (ancestor != null) {
l.add(ancestor);
printAncestor(ancestor, l);
}
}
}
# 运行结果
类名 Class:
lesson10.Student
修饰符 Modifiers:
public
泛型参数 Type Parameters:
T
接口 Implemented Interfaces:
interface java.io.Serializable
继承路径 Inheritance Path:
lesson10.People
java.lang.Object
注解 Annotations:
@lesson10.MyAnnotation(value=学生类)
获取字段
获取方法
获取构造方法
getDeclaredXxx() 可以获取
private和protected类型的字段/方法,但无法获取继承过来(父类)的字段/方法。
getXxx() 可以获取继承过来(父类)的字段/方法,但是只能得到
public类型的字段/方法,无法获取private和protected类型的字段/方法。
例如:
| 方法 | 返回类型 | 是否获取父类字段 | 是否获取私有字段 |
|---|---|---|---|
| getDeclaredField(name) | Field | × | √ |
| getField(name) | Field | √ | × |
| getDeclaredFields() | Field[] | x | √ |
| getFields() | Field[] | √ | × |
部分实例代码:
Class<?> c = Class.forName("lesson10.lesson1002.Student"); // 类路径
Field[] declaredFields = c.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println("declaredField:" + field.toGenericString());
}
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println("field:" + field.toGenericString());
}
基本类型: field.setInt(object, val) field.setFloat(object, val)…
应用类型: field.set(object,otherObj)
public class Student {
public String name;
public int age;
private float height;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
public class Demo {
public static void main(String[] args) {
try {
Student s = new Student();
Class<?> c = s.getClass();
Field name = c.getDeclaredField("name");
name.set(s, "小明");
Field age = c.getDeclaredField("age");
age.setInt(s, 18);
Field height = c.getDeclaredField("height");
// height.setFloat(s, 180f); // 错误 私有变量无法赋值
System.out.println(s);
} catch (NoSuchFieldException | IllegalAccessException x) {
x.printStackTrace();
}
}
}
反射调用对象的方法格式如: method.invoke(object, param1, param2)
public class Student {
public String setName(String name, int age) {
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
return "设置成功";
}
}
public class Demo {
public static void main(String[] args) {
try {
Student s = new Student();
Class<?> c = s.getClass();
Method method = c.getDeclaredMethod("setName", String.class, int.class);
method.invoke(s, "小明", 18);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
两种方式
Constructor constructor.newInstance();public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
public class Demo {
public static void main(String[] args) {
Class<?> c = Student.class;
try {
Student s1 = (Student) c.newInstance();
System.out.println(s1);
Constructor<?> ctor1 = c.getDeclaredConstructor();
Student s2 = (Student) ctor1.newInstance();
System.out.println(s2);
// 传递参数
Constructor<?> ctor2 = c.getDeclaredConstructor(String.class);
Student s3 = (Student) ctor2.newInstance("张三");
System.out.println(s3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射机制非常重要,很多主流的框架都用到了反射。反射是高级程序员必须要掌握的,它的魅力无穷。
关注微信公众号:小虎哥的技术博客,每天一篇文章,让你我都成为更好的自己。
