在Object类中定义了以下的方法,此方法将被所有子类继承:
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例。每一个运行时类只加载一次。通过Class可以完整地得到一个类中的完整结构。
// 1.调用运行时类本身的.class属性
Class class1 = String.class;
System.out.println(class1.getName());
// 2.通过运行时类的对象获取
String string = new String();
Class class2 = string.getClass();
System.out.println(class2.getName());
// 3.通过Class的静态方法获取(通过此方式体会反射的动态性)
String className = "java.lang.String";
Class class3 = null;
try {
class3 = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(class3.getName());
// 4.通过类的加载器(了解)
ClassLoader classLoader = this.getClass().getClassLoader();
Class class4 = null;
try {
class4 = classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(class4.getName());
System.out.println(class1 == class2); // true
System.out.println(class2 == class3); // true
System.out.println(class3 == class4); // true
类加载器:
@Test
public void test4() throws ClassNotFoundException, IOException {
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
ClassLoader loader2 = loader1.getParent();
ClassLoader loader3 = loader2.getParent();
System.out.println(loader1); // jdk.internal.loader.ClassLoaders$AppClassLoader@28c97a5
System.out.println(loader2); // jdk.internal.loader.ClassLoaders$PlatformClassLoader@24269709
System.out.println(loader3); // null
Class class1 = Person.class;
ClassLoader loader4 = class1.getClassLoader();
System.out.println(loader4); // jdk.internal.loader.ClassLoaders$AppClassLoader@28c97a5
// 测试某个类由哪个类加载器进行加载
String className = "java.lang.Object";
Class class2 = Class.forName(className);
ClassLoader loader5 = class2.getClassLoader();
System.out.println(loader5); // null
// 关于类加载器的一个主要方法
// 获取包下的配置文件
ClassLoader loader6 = this.getClass().getClassLoader();
InputStream is = loader6.getResourceAsStream("day20\\jdbc.properties"); // 获取类路径下的指定文件的输入流
// 获取工程目录下的配置文件
// FileInputStream is = new FileInputStream(new File("jdbc.properties"));
Properties pros = new Properties();
pros.load(is);
String name = pros.getProperty("user");
System.out.println(name); // runner
System.out.println(pros.getProperty("password")); // 123456
}
String className = "day20.Person";
Class class1 = Class.forName(className);
// 方法一:
Object obj = class1.newInstance(); // 已弃用
Person person = (Person) obj;
// 方法二:
Constructor constructor = class1.getConstructor(String.class);
Person person2 = (Person) constructor.newInstance("hello");
Class class1 = Person.class;
// 1.getFields(): 只能获取到运行时类中及其父类中声明为public的属性
Field[] fields = class1.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
// 2.getDeclaredFields(): 获取运行时类本身声明的所有的属性
Field[] fields1 = class1.getDeclaredFields();
for(Field field : fields1) {
// System.out.println(field);
// 1.获取每个属性的权限修饰符
int i = field.getModifiers();
System.out.print(Modifier.toString(i) + " ");
// 2.获取属性的类型
Class type = field.getType();
System.out.print(type.getName() + " ");
// 3.获取属性名
System.out.println(field.getName());
}
// 1.getMethods():获取运行时类及其父类中所有的声明为public的方法
Method[] methods = class1.getMethods();
// 2.getDeclaredMethods():获取运行时类本身声明的所有的方法
Method[] methods2 = class1.getDeclaredMethods();
// 获取注解 权限修饰符 返回值类型 方法名 形参列表 异常
for(Method method : methods2) {
// 1.注解
Annotation[] anns = method.getAnnotations();
for(Annotation ann : anns) {
System.out.println(ann);
}
// 2.权限修饰符
System.out.print(Modifier.toString(method.getModifiers()) + " ");
// 3.返回值类型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " ");
// 4.方法名
System.out.print(method.getName());
// 5.形参列表
System.out.print("(");
Class[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
System.out.print(params[i].getName() + " args-" + i + " ");
}
System.out.print(")");
// 6.异常类型
Class[] exps = method.getExceptionTypes();
if (exps.length != 0) {
System.out.print(" throws ");
}
for (int i = 0; i < exps.length; i++) {
System.out.print(exps[i].getName() + " ");
}
System.out.println();
}
Constructor[] cons = class1.getConstructors();
Constructor[] cons1 = class1.getDeclaredConstructors();
// 1.获取运行时类的父类
Class superClass = clazz.getSuperclass();
// 2.获取带泛型的父类
Type type = class1.getGenericSuperclass();
// 获取父类的泛型
ParameterizedType param = (ParameterizedType) type;
Type[] ars = param.getActualTypeArguments();
// 3.获取实现的接口
Class[] interfaces = class1.getInterfaces();
// 4.获取所在的包
Package package1 = class1.getPackage();
// 5.获取注解
Annotation[] anns = class1.getAnnotations();
// 6.获取内部类
Class[] classes = class1.getDeclaredClasses();
Class class1 = Person.class;
//1.获取指定的属性
//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
Field name = class1.getField("name");
//2.创建运行时类的对象
Person person = (Person) class1.newInstance();
//3.将运行时类的指定的属性赋值
name.set(person, "hello");
name.get(person); // 获取该属性值
// getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
Field age = class1.getDeclaredField("age");
age.setAccessible(true); // 由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。
age.set(person, 20);
Class class1 = Person.class;
//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
Method method = class1.getMethod("show");
Person person = new Person();
// 调用指定的方法:Object invoke(Object obj,Object ... obj)
Object returnVal = method.invoke(person);
Method method2 = class1.getMethod("toString");
Object returnVal1 = method2.invoke(person);
// 对于运行时类中静态方法的调用
Method method3 = class1.getMethod("Info");
method3.invoke(Person.class);
method3.invoke(null);
// getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
Method method4 = class1.getDeclaredMethod("display", String.class, Integer.class);
method4.setAccessible(true);
Object returnVal2 = method4.invoke(person, "hhhh", 3);
Class class1 = Person.class;
Constructor constructor = class1.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Person person = (Person) constructor.newInstance("xixi", 20);
Java学习笔记——设计模式:动态代理
相关阅读:
java反射机制简单总结
注:以上笔记参考自尚硅谷