【java基础】反射及练习

reflect : 反射,映射
类加载到内存中:将类的信息读取到内存中去(class文件读到内存中去)

(一)创建对象的两个不同时机:
(1)编译时创建对象:new Person(""); (弊端:对象改变时需要不断修改源代码)
(2)运行时创建对象:首先要获取class文件的信息 ,java中提供了一个类Class类
(二)Class类获得对象三种方法:
(1)

Class clazz1=Class.forName(""); 

注:引号""里面放的是包名.类名(通过对应java文件下的文件右键copyQualifiedName得到)
(2)

Class clazz2=类名.class;

(3)

Class clazz3=对象名.getClass();

注:上述clazz1 clazz2 clazz3对象都是同一个对象(因为读取的都是同一个类的相同的class文件)
(三)Class类的对象获取构造方法:
Class对象名.getConstructors():只能得public修饰的所有构造方法
Class对象名.getDelcaredConstructors():得到所有构造方法
Class对象名.getConstructors():只能得到public修饰的一个构造方法 Class对象名.getDelcaredConstructors():得到一个构造方法
(四)通过构造方法(有参或无参)可以创建其相对应的对象实例。

Object obj=构造方法对象名.newInstance();

(五)Class类的对象获取普通方法(同构造方法):
Class对象名.getMethods():只能得public修饰的所有方法
Class对象名.getDelcaredMethods():得到所有方法
Class对象名.getMethod():能得到public修饰的一个方法
Class对象名.getDeclaredMethod():得到一个方法
(六)Class类的对象获取属性(同构造方法),但一般实体类的属性都为私有变量,且多为一次取一个,故getDeclaredField(Field field)最为常用。
(七)以reflect包下的拥有姓名和年龄属性的Person实体类为例,
例1:
运行时(加载类文件的方式)创建Person对象

Class clazz=Class.forName("reflect.Person");//创建Class类对象
Constructor c=clazz.getConstructor();//创建无参构造变量
Object obj=c.newInstance();//用该无参构造变量创建Person对象实例

例2:

Class clazz=Class.forName("reflect.Person");//创建Class类对象
Constructor c=clazz.getConstructor(String.class,int.class);//创建有参构造对象
Object obj=c.newInstance("张三",20);
//用该有参构造对象创建Person对象实例

例3:
运行时(加载类文件的方式)通过无参构造创建Person对象并调用其display方法(公有无参方法),设定姓名属性name为”张三”(私有属性)

Class clazz=Class.forName("reflect.Person");//创建Class类对象
Constructor c=clazz.getConstructor();//创建无参构造对象
Object obj=c.newInstance();//用该无参构造对象创建Person对象实例
Method m=clazz.getMethod("display", null);//创建方法对象
m.invoke(obj);//执行方法
Field field=clazz.getDeclaredField("name");//创建私有变量对象
field.setAccessible(true);//私有变量设定取出或方法执行时需要得到权限,setAccessible(true);使其得到权限。
field.set(obj, "张三");//设定这个属性

(八)练习
1.写一个方法,此方法可将obj对象中名为propertyName的属性的值设置为value
在这里插入图片描述

class Person {
	private String name;
	private int age;
	public Person() {
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
public class ReflectTest {
	public static void setProperty(Object obj, String propertyName, Object value) throws Exception{
		Class clazz=obj.getClass();
		Field fName=clazz.getDeclaredField(propertyName);
		fName.setAccessible(true);
		fName.set(obj, value);
	}
	public static void main(String[] args) throws Exception{
		Person p=new Person();
		setProperty(p, "name", "范冰冰");
		setProperty(p, "age", 23);
		System.out.println(p);
	}
}

2.用键盘输入一个字符串,该字符串就是类的全名,使用反射机制创建该类的对象,并调用该对象中的方法showString

public class ReflectTest {
	public static void main(String[] args) throws Exception{
		System.out.println("请输入类的全名:");
		Scanner input=new Scanner(System.in);
		String s=input.next();
		Class clazz=Class.forName(s);
		Constructor c=clazz.getDeclaredConstructor();
		Object obj=c.newInstance();
		Method m=clazz.getDeclaredMethod("showString");
		m.setAccessible(true);
		m.invoke(obj);
	}
}

3.(1)写一个config.properties命名的配置文件,内容为类的完整名称(reflect.Person),放置在src下
(src路径:E:\Users\Administrator\workspace\Learning\src)
(2) 写一个程序,读取这个Properties配置文件,获得类的完整名称并加载这个类
(3)用反射 的方式运行display方法

public class ReflectTest3 {
	//读取并返回指定路径文件内容
	public static String getFileProperties(String path) throws IOException{
		FileInputStream fi=new FileInputStream(path);
		int len;
		StringBuffer sb=new StringBuffer();
		while((len=fi.read())!=-1){
			sb.append((char)len);
		}
		fi.close();
		return sb.toString();	
	}
	public static void main(String[] args) throws Exception {
		String property=getFileProperties("E:\\Users\\Administrator\\workspace\\Learning\\src\\config.properties");//获取src下配置文件的完整内容(类的全名)
		Class clazz=Class.forName(property);
		Constructor c=clazz.getDeclaredConstructor();
		Object obj=c.newInstance();
		Method m=clazz.getDeclaredMethod("display");
		m.setAccessible(true);
		m.invoke(obj);
	}

//IO流读取文件方法可参考以下链接:
【java基础】输入输出流及练习

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值