获取Class对象的三种方式
public class Test01 {
public static void main(String[] args) {
// 通过 类的 Class对象 获取类的加载器
// ClassLoader cl1 = String.class.getClassLoader();
// System.out.println(cl1);
//
// System.out.println(Test01.class.getClassLoader());
//调用类的 class 属性
//Class<Test01> c1 = Test01.class;
Class<?> c1 = Test01.class;
//调用对象的 getClass 方法
Test01 t1 = new Test01();
Class<? extends Test01> c2 = t1.getClass();
//Class<Test01> c3 = (Class<Test01>) t1.getClass();
Class<?> c4 = t1.getClass();
//调用 Class 类的 forName 静态方法
String className = "code17_reflect.Test01";// 类的全名
try {
Class<?> c5 = Class.forName(className);// 会执行类的加载
System.out.println(c1 == c2);// true
System.out.println(c1 == c5);// true
System.out.println(c2 == c5);// true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
有关属性的方法
public class TestField {
public static void main(String[] args) {
Class<?> c = Stu.class;
// 1. 获取 当前类 以及 其超类 中所有 public 修饰的属性
Field[] fields = c.getFields();
// 2. 获取 当前类中 所有属性 (含 private)
fields = c.getDeclaredFields();
for (Field f : fields) {
// 获取属性的 修饰符、类型、名称
int modifiers = f.getModifiers();
System.out.print(Modifier.toString(modifiers));
System.out.print(" ");
Class<?> fieldType = f.getType();
System.out.print(fieldType.getName());
System.out.print(" ");
String name = f.getName();
System.out.println(name);
}
System.out.println("-----------------");
try {
// 3.根据属性名 获取 当前类 以及 其超类 中对应的 public 修饰的属性(同名属性, 只能获取到自己的)
Field f = c.getField("name");
System.out.println("name : " + f);
} catch (NoSuchFieldException e) {
// 没有该属性 或 属性不是public 修饰的
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
try {
// 4. 根据属性名 获取 当前类中 指定属性 (含 private)
Field f = c.getDeclaredField("age");
System.out.println("age : " + f);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
其他方法
public class TestClass {
public static void main(String[] args) {
//Class c = Stu.class;
Class<?> c = Stu.class;
//Class<Stu> c = Stu.class;
System.out.println("类全名:" + c.getName());// 包名.类名
System.out.println("简单类名:" + c.getSimpleName());
// 有很多的方法, 用于判断类的类型
System.out.println("是否是接口:" + c.isInterface());
// 获取父类
Class<?> superClass = c.getSuperclass();
System.out.println("父类名:" + superClass.getName());
// 获取实现的接口
Class<?>[] interfaces = c.getInterfaces();
System.out.println("实现的接口:");
for (Class<?> ci : interfaces) {
System.out.println("\t" + ci.getName());
}
// 获取类的修饰符
int modifiers = c.getModifiers();
// Modifier.toString(mod) 把int值描述的修饰符, 转换为字符串描述的修饰符
System.out.println("modifiers:" + Modifier.toString(modifiers));
// 获取包
Package pkg = c.getPackage();
System.out.println("包:" + pkg.getName());
try {
// 使用无参构造, 创建对象
Object instance = c.newInstance();
// Class<Stu> 的效果
//Stu stu = c.newInstance();
System.out.println("instance:" + instance);
} catch (InstantiationException e) {
// 一般表示没有无参构造方法
e.printStackTrace();
} catch (IllegalAccessException e) {
// 构造方法不能直接访问, 例如 构造方法修饰符是 private
e.printStackTrace();
}
}
}
访问对象属性
private static void f2() throws Exception {
Class<?> c = Stu.class;
// 准备用于访问属性时需要的对象
Object stu = c.newInstance();
Field f = c.getDeclaredField("age");
// 如果属性是私有的, 如果任然需要强制访问, 则需要设置 允许访问
// 只对当前的 Field对象有效
f.setAccessible(true);// 一般被称为破坏封装
// 如果访问的属性是 静态的, 则不需要传入对象, 传入 null
// 赋值
// 正常的访问: 对象.属性名 = 值
try {
// 反射的操作: 设置指定对象的该属性的值
f.set(stu, 20);
} catch (IllegalArgumentException e) {
// 参数类型错误
e.printStackTrace();
} catch (IllegalAccessException e) {
// 无法直接访问, 修饰符问题
e.printStackTrace();
}
// 取值
// 正常的访问: 变量 = 对象.属性名
// 反射操作: 获取指定对象的该属性值
Object value = f.get(stu);
// 需要使用对应的类型则需要强制转换
Integer age = (Integer) value;
System.out.println("age:" + age);
}
访问方法
private static void f2() throws Exception {
Class<?> c = Stu.class;
try {
// 创建对象, 方便执行对象的指定方法
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("talk", String.class);
// 访问受限制时, 可以设置 允许访问, 这样就可以正常访问方法
m.setAccessible(true);
// 如果访问的方法是 静态的, 则不需要传入对象, 传入 null
// 执行方法
// 正常操作: 接收返回值 = 对象.方法(参数值);
// 反射操作: 使用指定对象来执行该方法, 并传入该方法需要的参数值
// 如果方法有返回值, 则 invoke 返回对应的值, 否则 invoke 返回 null
Object returnValue = m.invoke(obj, "hello world");
System.out.println("returnValue:" + returnValue);
} catch (IllegalArgumentException e) {
// 参数错误
e.printStackTrace();
} catch (InvocationTargetException e) {
// 使用的对象有问题
e.printStackTrace();
} catch (IllegalAccessException e) {
// 访问受限制, 例如 private
e.printStackTrace();
}
}
private static void f1() {
Class<?> c = Stu.class;
// 1. 获取 当前类 以及 其超类 中所有 public 修饰的方法
Method[] methods = c.getMethods();
// 2. 获取 当前类中 所有方法 (含 private)
// methods = c.getDeclaredMethods();
for (Method m : methods) {
// 修饰符、返回值类型、方法名、参数列表、抛出的异常
String modifiers = Modifier.toString(m.getModifiers());
Class<?> returnType = m.getReturnType();
String name = m.getName();
//Parameter[] parameters = m.getParameters();
Class<?>[] parameterTypes = m.getParameterTypes();
Class<?>[] exceptionTypes = m.getExceptionTypes();
System.out.println(
modifiers + " "
+ returnType.getSimpleName() + " "
+ name + "("
+ Arrays.toString(parameterTypes) + ") "
+ "throws " + Arrays.toString(exceptionTypes) + " { }"
);
}
System.out.println("===============");
try {
// 3.根据方法名,方法的参数列表 获取 当前类 以及 其超类 中对应的 public 修饰的方法(重写的方法, 只能获取到自己的)
// 参数列表是 参数的类型, 参数类型的顺序
// 没有参数的方法, 不用传入参数类型
Method m = c.getMethod("study", String.class, int.class);
System.out.println("study:" + m);
} catch (NoSuchMethodException e) {
// 没有对应的方法
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
try {
// 4. 根据方法名,方法的参数列表 获取 当前类中 指定方法 (含 private)
Method m = c.getDeclaredMethod("talk", String.class);
System.out.println("talk:" + m);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
有关declared
// 1. 获取 当前类 中所有 public 修饰的构造方法
Constructor<?>[] constructors = c.getConstructors();
// 2. 获取 当前类中 所有构造方法 (含 private)
constructors = c.getDeclaredConstructors();
和配置文件的操作
// 通过如下方式,即使代码换位置了,仍然试用,注意:此处的配置文件必须放在src根目录下
// 方式一(通用方式):
String path = Thread.currentThread().getContextClassLoader().getResource("配置文件名.properties").getPath();
FileReader reader = new FileReader(path);
Properties pro = new Properties();
// 方式二:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("配置文件名.properties")
Properties pro = new Properties();
pro.load(reader);
// 关闭流
reader.close();
String className = pro.getProperty(pro);
// 通过反射机制实例化对象```
Class c = Class.forName(className);
方式三:
// 注意:配置文件名不要加后缀,且扩展名必须是properties结尾
ResourceBundle bundle = ResourceBundle.getBundle("配置文件名");
String className = bundle.getString("className");