JavaSE——反射

获取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");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值