红色标注为当前重点
反射机制概述: 动态语言的特性、通过对象查看类的内部信息 -> 运行时可调整自身结构。
反射能做的事?
java中类本身也是对象,因为所有类都是 java.lang.Class类的对象。
反射与权限修饰符疑问 ? : 反射(能不能调用的问题)、类的封装性(建不建议调用的问题)
“new或反射来实例化” 的疑问?(是否需要动态特性的问题)
反射的案例
下列文件放置于com.xj.java包下。
代码逻辑:
从test1(),test2(),test3(),test4()依次介绍Class实例创建,使用Class实例来创建目标运行时实例,体会反射的动态性,反射(Class实例)来获取任何结构信息
RejectionTest.javaPerson.javaMyInterface.javaMyAnnotation.java
RejectionTest.java
package com.xj.java;
import org.junit.jupiter.api.Test;
import java.lang.reflect.*;
import java.util.Random;
/**
* @author jia
* @create 2021-12-21 7:43 下午
*/
public class RejectionTest {
@Test
public static Class test1() throws Exception {
/**
* Class实例对应着一个运行时类(含void、注解、数组等任意结构),体现java万事万物皆对象。
* 有4种方法获得该Class实例
* */
// 方法1
Class clazz = Person.class;
// 方法2
Class clazz2 = new Person().getClass();
// 方式3 全类名 (最常使用)
Class clazz3 = Class.forName("com.xj.java.Person");
// 方式4 类的加载器 (了解)
ClassLoader classLoader = RejectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("com.xj.java.Person");
// 多种方式,其实是同一个运行时类
System.out.println(clazz == clazz2);
System.out.println(clazz == clazz3);
System.out.println(clazz == clazz4);
System.out.println(clazz3);
return clazz3;
}
@Test
public Person test2() throws Exception {
/**
* 使用反射(Class实例)来创建运行时实例。
* 注意:必须提供空参构造器,一般为public权限。
* */
Class clazz = test1();
// Person obj = (Person) clazz.newInstance();
Person obj = (Person) clazz.getDeclaredConstructor().newInstance();
System.out.println(obj);
return obj;
}
@Test
public void test3() throws Exception{
/**
* 体会反射的动态性
* */
int t = new Random().nextInt(2);
String classPath = null;
switch (t){
case 0:
classPath = "com.xj.java.Person";
break;
case 1:
classPath = "java.lang.Object";
break;
}
Object obj = getInstance(classPath);
System.out.println(obj);
}
public Object getInstance(String classPath) throws Exception {
Class clazz = Class.forName(classPath);
// Object obj = clazz.newInstance();
Object obj = clazz.getDeclaredConstructor().newInstance();
return obj;
}
@Test
public void test4() throws Exception{
/**
反射(Class实例)来获取任何类信息,包括注解等
*/
// Class实例
Class clazz = Class.forName("com.xj.java.Person");
// 获得空参构造器结构
Constructor declaredConstructor = clazz.getDeclaredConstructor();// 获取构造器,一般获取空参构造器
declaredConstructor.setAccessible(true);
// 利用构造器结构来实例化对象
Person person = (Person) declaredConstructor.newInstance();
// 调用具体实例的方法
Method show = clazz.getDeclaredMethod("show", String.class);// 方法名,形参列表
show.setAccessible(true); // 无视权限限制
Method info = clazz.getDeclaredMethod("info");// 静态方法
info.setAccessible(true);
Object showreturnval = show.invoke(person, "中国");// 具体实例,方法形参
Object inforeturnval = info.invoke(person); // 静态方法(此处方法无形参), 方法无返回值依然要可接收返回值,则此处返回null。
System.out.println("show方法返回值:" + showreturnval);
System.out.println("info静态方法的空返回值:" + inforeturnval);
// 修改和访问具体实例额的属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(person,"good man");
System.out.println("对象的name属性:" + name.get(person));
// 访问注解信息
MyAnnotation myAnnotation = (MyAnnotation)clazz.getDeclaredAnnotation(MyAnnotation.class);// 获取注解
System.out.println("注解的value信息:" + myAnnotation.value());
// 获取包结构
Package pack = clazz.getPackage();
System.out.println("包名:"+pack);
// 获取接口结构
Class[] interfaces = clazz.getInterfaces();
for (Class v : interfaces){
System.out.println(v);
}
// 获得父类
Class superClazz = clazz.getSuperclass();
System.out.println("父类:" +superClazz.getName());
// 获得带泛型的父类
Type genericSuperclass1 = clazz.getGenericSuperclass();
System.out.println("带泛型的父类:" + genericSuperclass1.getTypeName());
// 获取泛型信息(包括泛型类、泛型接口)
Type genericSuperclass = clazz.getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments){
System.out.println("类的泛型信息:" + type.getTypeName());
}
Type[] genericInterfaces = clazz.getGenericInterfaces();
for (Type type : genericInterfaces){
System.out.println("接口的泛型信息:" + type.getTypeName());
}
}
}
国籍:中国,名字:null,年龄:0 我是静态方法 show方法返回值:中国 info静态方法的空返回值:null 对象的name属性:good man 注解的value信息:my annotation for class 包名:package com.xj.java interface java.lang.Comparable interface com.xj.java.MyInterface 父类:com.xj.java.Creater 带泛型的父类:com.xj.java.Creater
类的泛型信息:java.lang.String 接口的泛型信息:java.lang.Comparable 接口的泛型信息:com.xj.java.MyInterface
Person.java
package com.xj.java;
import java.io.Serializable;
/**
* @author jia
* @create 2021-12-21 7:42 下午
*/
class Creater<T> implements Serializable {
private char gender;
public double weight;
private void breath(){
System.out.println("生物呼吸");
}
private void eat(){
System.out.println("生物进食");
}
}
@MyAnnotation(value="my annotation for class")
public class Person extends Creater<String> implements Comparable<String>,MyInterface{
public String name;
private int age;
public Person(){};
private Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@MyAnnotation(value="my annotation for show method")
@Override
public String show(String nation){
System.out.println("国籍:" + nation + ",名字:" + this.name + ",年龄:" + this.age);
return nation;
}
@MyAnnotation(value="my annotation for info static method")
private static void info(){
System.out.println("我是静态方法");
}
@Override
public int compareTo(String o) {
return 0;
}
}
MyAnnotation.java
package com.xj.java;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
/**
* @author jia
* @create 2021-12-22 10:49 上午
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME) // 持续到RUNTIME
public @interface MyAnnotation {
String value() default "hello";
}
MyInterface.java
package com.xj.java;
/**
* @author jia
* @create 2021-12-22 10:51 上午
*/
public interface MyInterface {
public String show(String nation);
}