反射
个人粗浅的对于反射的理解:通过调用Class静态方法forName()来动态地获取指定的Class实例(加载到内存中的类,又称运行时类),
然后调用各种方法进行创建对象或获取及调用指定结构(属性、方法、构造器等)。
1 package com.fly.reflection; 2 3 import org.junit.Test; 4 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.lang.annotation.Annotation; 8 import java.lang.reflect.*; 9 import java.util.Properties; 10 11 public class ReflectionTest { 12 13 /** 14 * 获取Class实例的方式 15 */ 16 @Test 17 public void test1() throws ClassNotFoundException { 18 //方式一:调用运行时类的属性 19 Class personClass1 = Person.class; 20 System.out.println(personClass1); 21 //方式二:通用运行时类的对象,调用getClass() 22 Person person = new Person(); 23 Class personClass2 = person.getClass(); 24 System.out.println(personClass2); 25 //方式三:调用Class静态方法 26 Class personClass3 = Class.forName("com.fly.reflection.Person"); 27 System.out.println(personClass3); 28 //方式四:使用类的加载器:ClassLoader 29 ClassLoader classLoader = ReflectionTest.class.getClassLoader(); 30 Class personClass4 = classLoader.loadClass("com.fly.reflection.Person"); 31 System.out.println(personClass4); 32 33 System.out.println(personClass1 == personClass2); 34 System.out.println(personClass1 == personClass3); 35 System.out.println(personClass1 == personClass4); 36 } 37 38 /** 39 * 读取配置文件 40 */ 41 @Test 42 public void test2() throws IOException { 43 Properties properties = new Properties(); 44 //方式一 此时文件默认在当前module下 45 //FileInputStream is = new FileInputStream("src\\reflection.properties"); 46 //方式二 此时文件默认在当前module的src下 47 ClassLoader classLoader = ReflectionTest.class.getClassLoader(); 48 InputStream is = classLoader.getResourceAsStream("reflection.properties"); 49 50 properties.load(is); 51 String username = properties.getProperty("username"); 52 String password = properties.getProperty("password"); 53 System.out.println("username = " + username + "password = " + password); 54 } 55 56 /** 57 * 根据Class实例来创建对象 58 */ 59 @Test 60 public void test3() throws IllegalAccessException, InstantiationException, ClassNotFoundException { 61 //获取Person类 62 Class clazz = Class.forName("com.fly.reflection.Person"); 63 //newInstance()里面调用了空参构造器(构造器权限需要足够访问) 64 Object person = clazz.newInstance(); 65 System.out.println(person); 66 67 } 68 69 /** 70 * 获取属性结构 71 */ 72 @Test 73 public void test4() { 74 Class<Person> clazz = Person.class; 75 //获取当前运行时类及父类中声明为public访问权限的属性 76 Field[] fields = clazz.getFields(); 77 for (Field field : fields) { 78 System.out.println(field); 79 } 80 System.out.println("*****************"); 81 //获取当前运行时类(不包含父类)的所有属性 82 Field[] declaredFields = clazz.getDeclaredFields(); 83 for (Field declaredField : declaredFields) { 84 System.out.println(declaredField); 85 } 86 System.out.println("*****************"); 87 for (Field field : declaredFields) { 88 //权限修饰符 89 int modifier = field.getModifiers(); 90 System.out.print(Modifier.toString(modifier) + "\t"); 91 //数据类型 92 Class type = field.getType(); 93 System.out.print(type.getName() + "\t"); 94 //变量名 95 String name = field.getName(); 96 System.out.print(name); 97 98 System.out.println(); 99 } 100 } 101 102 /** 103 * 获取方法结构 104 */ 105 @Test 106 public void test5() throws NoSuchMethodException { 107 Class<Person> clazz = Person.class; 108 //获取当前运行时类及所有父类中声明为public权限的方法 109 Method[] methods = clazz.getMethods(); 110 for (Method method : methods) { 111 System.out.println(method); 112 } 113 System.out.println("**************"); 114 //获取当前运行时类(不包含父类)的所有方法 115 Method[] declaredMethods = clazz.getDeclaredMethods(); 116 for (Method method : declaredMethods) { 117 System.out.println(method); 118 } 119 System.out.println("*****************"); 120 Method showScore = clazz.getDeclaredMethod("showScore", double.class); 121 //获取方法声明的注解 122 Annotation[] annotations = showScore.getAnnotations(); 123 for (Annotation annotation : annotations) { 124 System.out.println(annotation); 125 } 126 //获取权限修饰符 127 int modifiers = showScore.getModifiers(); 128 System.out.println(Modifier.toString(modifiers)); 129 //获取返回值类型 130 Class returnType = showScore.getReturnType(); 131 System.out.println(returnType.getName()); 132 //获取方法名 133 String name = showScore.getName(); 134 System.out.println(name); 135 //获取形参列表 136 Class[] parameterTypes = showScore.getParameterTypes(); 137 System.out.println(parameterTypes[0].getName()); 138 //获取抛出的异常 139 Class[] exceptionTypes = showScore.getExceptionTypes(); 140 System.out.println(exceptionTypes[0].getName()); 141 142 } 143 144 /** 145 * 获取构造器结构 146 * 构造器与方法类似,可获取构造器的权限修饰符等 147 */ 148 @Test 149 public void test6() { 150 Class clazz = Person.class; 151 //获取当前运行时类(不包含父类)中声明为public权限的构造器 152 Constructor[] constructors = clazz.getConstructors(); 153 for (Constructor constructor : constructors) { 154 System.out.println(constructor); 155 } 156 System.out.println("*************"); 157 //获取当前运行时类(不包含父类)的所有构造器 158 Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); 159 for (Constructor constructor : declaredConstructors) { 160 System.out.println(constructor); 161 } 162 } 163 164 /** 165 * 获取运行时类的父类或父类的泛型 166 */ 167 @Test 168 public void test7() { 169 Class clazz = Person.class; 170 //获取运行时类的父类 171 Class superclass = clazz.getSuperclass(); 172 System.out.println(superclass); 173 System.out.println("**********"); 174 //获取运行时类的带泛型的父类 //Class<T> implements Type 175 Type genericSuperclass = clazz.getGenericSuperclass(); 176 System.out.println(genericSuperclass); 177 //获取运行时类的带泛型的父类的泛型 178 ParameterizedType paramType = (ParameterizedType) genericSuperclass; 179 Type[] arguments = paramType.getActualTypeArguments(); 180 System.out.println(arguments[0].getTypeName() + "或者" + ((Class)arguments[0]).getName()); 181 182 } 183 184 /** 185 * 获取运行时类及父类实现的接口 186 */ 187 @Test 188 public void test8() { 189 Class clazz = Person.class; 190 //获取运行时类实现的接口 191 Class[] interfaces = clazz.getInterfaces(); 192 for (Class anInterface : interfaces) { 193 System.out.println(anInterface); 194 } 195 System.out.println("**********"); 196 //获取运行时类的父类实现的接口 197 Class superclass = clazz.getSuperclass(); 198 Class[] superInterfaces = superclass.getInterfaces(); 199 System.out.println(superInterfaces[0]); 200 } 201 202 /** 203 * 获取运行时类所在的包 204 */ 205 @Test 206 public void test9() { 207 Class clazz = Person.class; 208 //获取运行时类所在的包 209 Package aPackage = clazz.getPackage(); 210 System.out.println(aPackage); 211 } 212 213 /** 214 * 获取运行时类声明的注解 215 */ 216 @Test 217 public void test10() { 218 Class clazz = Person.class; 219 //获取运行时类声明的注解 220 Annotation[] annotations = clazz.getAnnotations(); 221 System.out.println(annotations[0]); 222 } 223 224 /** 225 * 调用运行时类中指定的属性 226 */ 227 @Test 228 public void test11() throws NoSuchFieldException, IllegalAccessException, InstantiationException { 229 Class<Person> clazz = Person.class; 230 //创建运行时类的对象 231 Person person = clazz.newInstance(); 232 //获取指定的属性,要求属性是public的 233 Field score = clazz.getField("score"); 234 /** 235 * 设置当前属性的值 236 * 参数一:指明是设置哪个对象的属性 237 * 参数二:属性值 238 */ 239 score.set(person,12.23); 240 /** 241 * 获取当前属性的值 242 * 参数一:获取哪个对象的属性值 243 */ 244 Object o = score.get(person); 245 System.out.println((double)o); 246 247 } 248 249 /** 250 * 调用运行时类中指定的属性 251 */ 252 @Test 253 public void test12() throws NoSuchFieldException, IllegalAccessException, InstantiationException { 254 Class<Person> clazz = Person.class; 255 //创建运行时类的对象 256 Person person = clazz.newInstance(); 257 //获取指定的属性 258 Field name = clazz.getDeclaredField("name"); 259 //将不是public修饰的属性设置为可访问的 260 name.setAccessible(true); 261 //设置指定对象当前属性的值 262 name.set(person,"Tom"); 263 //获取指定对象当前属性的值 264 String o = (String) name.get(person); 265 System.out.println(o); 266 267 } 268 269 /** 270 * 调用运行时类中指定的方法 271 */ 272 @Test 273 public void test13() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { 274 Class<Person> clazz = Person.class; 275 //创建运行时类的对象 276 Person person = clazz.newInstance(); 277 /** 278 * 获取指定的方法 279 * 参数一:方法名 280 * 参数二:形参列表的类型 281 */ 282 Method showScore = clazz.getDeclaredMethod("showScore", double.class); 283 //将不是public修饰的方法设置为可访问的 284 showScore.setAccessible(true); 285 /** 286 * 执行方法:返回值即为方法执行后的返回值 287 * 参数一:方法的调用者 288 * 参数二:给方法形参赋值的实参 289 */ 290 Object invoke = showScore.invoke(person, 23.45); 291 System.out.println((double)invoke); 292 293 /******************调用静态方法******************/ 294 Method display = clazz.getDeclaredMethod("display"); 295 display.setAccessible(true); 296 //如果被调用的方法没有返回值,则invoke()返回null 297 display.invoke(clazz); 298 display.invoke(null); 299 300 } 301 302 /** 303 * 调用运行时类中指定的构造器 304 */ 305 @Test 306 public void test14() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 307 Class<Person> clazz = Person.class; 308 /** 309 * 获取指定的构造器 310 * 参数:形参列表的类型 311 */ 312 Constructor<Person> declaredConstructor = clazz.getDeclaredConstructor(String.class); 313 //将不是public修饰的构造器设置为可访问的 314 declaredConstructor.setAccessible(true); 315 //创建对象 316 Person person = declaredConstructor.newInstance("Tom"); 317 System.out.println(person); 318 } 319 }
下面是上面代码使用过的类、接口、注解
public class Creature<T> implements Serializable { private char gender; public double weight; T describe; private void breath() { System.out.println("生物呼吸"); } public void eat() { System.out.println("生物吃东西"); } } @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value() default "hello"; } public interface MyInterface { void impleMethod(); } @MyAnnotation(value = "hi") public class Person extends Creature<String> implements Comparable<Person>, MyInterface { private String name; int age; public double score; public Person() { } @MyAnnotation(value = "abc") private Person(String name) { this.name = name; } Person(String name, int age, double score) { this.name = name; this.age = age; this.score = score; } public void showInfo() { System.out.println("showInfo()...."); } private static void display() { System.out.println("display......."); } @MyAnnotation private double showScore(double score) throws RuntimeException { System.out.println("showScore:" + score); return score; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Person o) { return 0; } @Override public void impleMethod() { System.out.println("我是人"); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现