一、反射
反射机制是java在实际开发中最常用到的,比如三大框架中都用到了反射机制。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性。
反射机制看似将java中常用的一条语句拆成许多语句,但是大大的提高了其灵活性。具体例子见如下代码:
首先定义一个javaBean用来封装数据:重写toString方法方便以后将类输出。
public class Bean implements Serializable{
private String id;
private String className;
public String description;
public Bean(String id) {
super();
this.id = id;
System.out.println("一个参数构造");
}
private Bean(String id, String className) {
super();
this.id = id;
this.className = className;
System.out.println("两个参数构造");
}
private int show(int age){
return age;
}
public static void main(String[] args){
System.out.println(Arrays.toString(args));
}
public Bean() {
System.out.println("无参构造");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public String toString() {
return "Bean [id=" + id + ", className=" + className + ",des=" + description + "]";
}
}
下面通过三种方式获取此javaBean的class对象:
public class ClassDemo {
@Test
public void Demo1() throws ClassNotFoundException {
//1,在开发中便于从配置文件中获取全限定类名
Class clazz = Class.forName("cn.ahut.gbl.Bean");
System.out.println(clazz);
}
@Test
public void Demo2() throws ClassNotFoundException {
//2,确定构造方法,不同方法形参列表时,需要通过类型获得
Class clazz = Bean.class;
System.out.println(clazz);
}
@Test
public void Demo3() throws ClassNotFoundException {
//3,方法内部使用获取
Bean bean = new Bean();
Class clazz = bean.getClass();
System.out.println(clazz);
}
}
二、通过反射机制获取javaBean中的公共和私有构造方法,具体代码如下:
public class ClassDemo2 {
@Test
public void Demo1() throws Exception {
//获取无参构造方法
Class clazz = Class.forName("cn.ahut.gbl.Bean");
Constructor con = clazz.getConstructor();
Object object = con.newInstance(); //对象进行实例化
}
@Test
public void Demo2() throws Exception {
//获取有参构造方法
//获取class对象
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//有一个参数的构造
Constructor con = clazz.getConstructor(String.class);
Object object = con.newInstance("abc123");
System.out.println(object);
}
@Test
//无参构造的简写
public void Demo3() throws Exception {
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//通过clazz直接创造
Object object = clazz.newInstance();
}
@Test
public void Demo4() throws Exception {
//获取指定类中的私有构造方法
//获取class对象
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//获取构造
/*clazz.getConstructor(....);指定类中公共的构造方法
* clazz.getDeclaredConstructor(....);指定类中任意的构造方法
*/
Constructor cons = clazz.getDeclaredConstructor(String.class,String.class);
//通知JVM运行私有构造参数 (默认不允许)
cons.setAccessible(true);
Object object = cons.newInstance("adf123","姓名");
System.out.println(object);
}
}
三、通过反射获取制定类中公共、私有和静态方法以及公共和私有的字段。具体代码如下:
public class ClassDemo3 {
@Test
//通过反射获取公共普通的方法
public void Demo1() throws Exception {
//获取类对象
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//实例化
Object object = clazz.newInstance();
//通过setId获取数据
Method method = clazz.getMethod("setId", String.class);
//设置数据,并执行方法
method.invoke(object, "ab001");
//打印数据
Method method1 = clazz.getMethod("getId");
String string = (String) method1.invoke(object);
System.out.println(string);
}
@Test
//通过反射获取私有普通的方法
public void Demo2() throws Exception {
//获取类对象
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//实例化
Object object = clazz.newInstance();
//通过setId获取数据
Method method = clazz.getDeclaredMethod("show", int.class);
method.setAccessible(true);
//设置数据
Object object2 = method.invoke(object, 18);
//打印数据
System.out.println(object2);
}
@Test
//通过反射获取静态主方法
public void Demo3() throws Exception {
//获取类对象,主方法是静态的,不需要实例化
Class clazz = Class.forName("cn.ahut.gbl.Bean");
//获取方法
Method method = clazz.getMethod("main", String[].class);
//执行main方法
/*第一个参数为实例对象(变量名),main方法是静态的,不需要
* 第二个参数为字符串数组,是实际参数
* 可变参数再执行的时候,JVM将里面的额参数打乱,变成多个参数,所以会报错
* 所以这里可以将数组强制转换成Object类型
*/
String[] args= {"张三","男","abc121"};
method.invoke(null, (Object)args);
}
@Test
//通过反射获取public字段
public void Demo4() throws Exception {
//获取类对象,
Class clazz = Class.forName("cn.ahut.gbl.Bean");
Object obj = clazz.newInstance();
//获取方法
Field field = clazz.getField("description");
//给字段赋值
field.set(obj, "描述");
//取出字段的值
String string = (String) field.get(obj);
System.out.println(string);
}
@Test
//通过反射获取private字段
public void Demo5() throws Exception {
//获取类对象,
Class clazz = Class.forName("cn.ahut.gbl.Bean");
Object obj = clazz.newInstance();
//获取方法
Field field = clazz.getDeclaredField("className");
field.setAccessible(true);
//给字段赋值
field.set(obj, "javaBean");
//取出字段的值
String string = (String) field.get(obj);
System.out.println(string);
}
}
四、properties是java中以键值对存储的,以.properties结尾,在开发中用作配置文件。在框架的开发中需要读取配置文件,进行动态的编码。下面展示如何写入和读取properties文件。
public class PropsDemo {
@Test
public void Demo1() throws IOException {
//properties的操作:写入文件
Properties properties = new Properties();
properties.setProperty("name", "老张");
properties.setProperty("sex", "男");
properties.setProperty("age", "65");
//将properties写入硬盘
Writer writer = new OutputStreamWriter(new FileOutputStream("1.properties"), "UTF-8");
properties.store(writer, "描述");
writer.close();
}
@Test
public void Demo2() throws IOException {
////properties的操作:读文件
//获得properties对象
Properties properties = new Properties();
//获得流资源
Reader reader = new InputStreamReader(new FileInputStream("1.properties"), "UTF-8");
//通过properties对象下载资源
properties.load(reader);
//遍历内容
for (String name : properties.stringPropertyNames()) {
String value = properties.getProperty(name);
System.out.println(name+":"+value);
}
}
}
五,下面编写一个Demo,看一下如何动态的获取配置文件中的内容来调用javaBean。
在这里我们分别编写beanConfig,bean和book三个javaBean文件,以及bean.properties和data.properties文件。bean.properties中存储的是data.properties文件的id和jabaBean的类对象,data.properties文件中存储的是对应javaBean中的具体数据。
如下所示:
public class BeanConfig {
private String id;
private String className;
Properties properties = new Properties();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "BeanConfig [id=" + id + ", className=" + className
+ ", properties=" + properties + "]";
}
}
public class Book {
private String bid;
private String title;
private String price;
public String getBid() {
return bid;
}
public void setBid(String bid) {
this.bid = bid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "Book [bid=" + bid + ", title=" + title + ", price=" + price
+ "]";
}
}
public class UserBean {
private String uid;
private String userName;
private String passWord;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "UserBean [uid=" + uid + ", userName=" + userName
+ ", passWord=" + passWord + "]";
}
}
下面通过读取properties中的内容为beanConfig添加字段信息:
public class DemoTest {
public BeanConfig getConfig() throws Exception {
//读取配置文件
BeanConfig beanConfig = new BeanConfig();
//读取bean.properties文件内容,获取ID和className
Properties properties = new Properties();
properties.load(new InputStreamReader(new FileInputStream("bean.properties"),"UTF-8"));
beanConfig.setId(properties.getProperty("id"));
beanConfig.setClassName(properties.getProperty("className"));
//System.out.println(beanConfig);
//读取data.properties文件内容
Properties dataProperties = new Properties();
dataProperties.load(new InputStreamReader(new FileInputStream("data.properties"),"UTF-8"));
for(String name : dataProperties.stringPropertyNames()){
System.out.println(name);
String value = dataProperties.getProperty(name);
beanConfig.getProperties().setProperty(name, value);
}
return beanConfig;
}
@Test
public void method1() throws Exception {
//真实数据
BeanConfig beanConfig = getConfig();
//使用数据创建javaBean实例,并为javaBean封装具体数据
Class clazz = Class.forName(beanConfig.getClassName());
Object object = clazz.newInstance();
//调用javaBean中的set方法进行封装
for(String name : beanConfig.getProperties().stringPropertyNames()){
String value = beanConfig.getProperties().getProperty(name);
//获得方法名
String methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
//调用set方法
Method method = clazz.getMethod(methodName, String.class);
method.invoke(object, value);
}
System.out.println(object);
}
管牛牛 发布了27 篇原创文章 · 获赞 6 · 访问量 2万+ 私信 关注