1.反射含义是什么?
Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。你仅仅传一个类的全包名路径,就能通过反射,来获取对应的类实例,我们一般会用Class类,来调用这个被反射的Objcet类下的,构造方法,属性,或方法等,反射在一些开源框架里用的非常之多,Spring,Struts,Hibnerate,MyBatics都有它的影子。
一句话就是:java 动态获取的类的方法属性以及动态调用对象的方法的功能叫做反射。
两种不同的状态:
静态编译: 在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
2.反射机制的优点与缺点?
优点:
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能
缺点:
(1)使用反射的性能较低
(2)使用反射相对来说不安全
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性
2.反射的用法和示例?
Java反射所需要的类并不多,主要有java.lang.Class类和java.lang.reflect包中的Field、Constructor、Method、Array类。
注意:Class类是Java反射的起源,针对任何一个你想探勘的类,只有先为它产生一个Class类的对象,接下来才能通过Class对象获取其他想要的信息。
java反射可以获取一下信息:Class 对象、类名、修饰符、包信息、父类、实现的接口、构造器、方法、变量、注解。
来来来,让我们创建一个对象,然后在分别尝试使用它的各种方法,本文不作详细的解释。
Person Class
public class Person implements Action {
private String name;
private int age;
private String head;
protected List<String> stringList = new ArrayList<>();
private String privateString = null;
public Person(String name) {
this.name = name;
}
public Person(String name, int age, String head) {
this.name = name;
this.age = age;
this.head = head;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("打印参数:" + name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", head='" + head + '\'' +
'}';
}
public Person(String name, String privateString) {
this.name = name;
this.privateString = privateString;
}
public void setPrivateString(String privateString) {
this.privateString = privateString;
}
private String getPrivateString() {
return this.privateString;
}
public List<String> getStringList() {
return this.stringList;
}
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
@Override
public void run() {
}
@Override
public void jump() {
}
@Override
public void rotate() {
}
}
Action 接口类
Person 子类 纯属测试一个方法
public class Hero extends Person {
public Hero(String name, int age, String head) {
super(name, age, head);
}
}
//获取Class对象
' Class className = Class.forName("com.java.study.reflect.Person");'
//即获取类名 又获取包名
' System.out.println("Name:" + className.getName());'
//仅仅获取类名 不获取包名
' System.out.println("SimpleName:" + className.getSimpleName());'
//获取类的 Modifiers 修饰符
int modifiers = className.getModifiers();
System.out.println("类是否为抽象的:" + Modifier.isAbstract(modifiers));
System.out.println("是否用Final修饰:" + Modifier.isFinal(modifiers));
System.out.println("isInterface:" + Modifier.isInterface(modifiers));
System.out.println("isNative:" + Modifier.isNative(modifiers));
System.out.println("isPrivate:" + Modifier.isPrivate(modifiers));
System.out.println("isProtected:" + Modifier.isProtected(modifiers));
System.out.println("isPublic:" + Modifier.isPublic(modifiers));
System.out.println("isStatic:" + Modifier.isStatic(modifiers));
System.out.println("isStrict:" + Modifier.isStrict(modifiers));
System.out.println("isSynchronized:" + Modifier.isSynchronized(modifiers));
System.out.println("isTransient:" + Modifier.isTransient(modifiers));
System.out.println("isVolatile:" + Modifier.isVolatile(modifiers));
//Hero Class
' Class hero = Class.forName("com.java.study.reflect.Hero");'
//获取包的信息
'System.out.println("包名:" + hero.getName());'
//获取父类信息 (然后可以获取父类的信息)
' System.out.println("Class 对象你可以访问类的父类:"+hero.getSuperclass().getName());' //类的接口
Class[] interfaces = className.getInterfaces();
if (interfaces.length > 0) {
System.out.println("集成接口的名字:" + interfaces[0].getName());
}
//根据 Class 对象来获取 Constructor 类
Constructor[] constructors = className.getConstructors();
if (constructors.length > 0) {
Class[] parameterTypes = constructors[0].getParameterTypes();
System.out.println("构造参数数组:" + parameterTypes[0]);
}
''
//采用反射返回一个字段的值
Field[] fields = className.getFields();
Person person = new Person("小明");
Field privateStringField = Person.class.getDeclaredField("name");
//setAccessible()方法会关闭指定类 Field 实例的反射访问检查,这行代码执行之后不论是私有的、受保护的以及包访问的作用域,
// 你都可以在任何地方访问,即使你不在他的访问权限作用域之内。但是你如果你用一般代码来访问这些不在你权限作用域之内的代码依然是不可以的,
// 在编译的时候就会报错。
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(person);
System.out.println("fieldValue = " + fieldValue);
//根据字段 返回一个私有方法
Person person2 = new Person("小明", "The Private Value");
Method privateStringMethod = Person.class.getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
String returnValue = (String) privateStringMethod.invoke(person2, null);
System.out.println("returnValue = " + returnValue);
//反射中的类型
Method method = Person.class.getMethod("getStringList", null);
Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) returnType;
Type[] typeArgument = type.getActualTypeArguments();
for (Type typeItem : typeArgument) {
Class typeArgClass = (Class) typeItem;
System.out.println("typeArgClass = " + typeArgClass);
}
}
Method method2 = Person.class.getMethod("setStringList", List.class);
Type[] genericParameterTypes = method2.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
if (genericParameterType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericParameterType;
Type[] parameterArgTypes = aType.getActualTypeArguments();
for (Type parameterArgType : parameterArgTypes) {
Class parameterArgClass = (Class) parameterArgType;
System.out.println("parameterArgClass = " + parameterArgClass);
}
}
}
'''