Java Reflect
Method method=demo.getMethod("sayChina");
method.invoke(demo.newInstance()); //调用Person的sayHello方法 method=demo.getMethod("sayHello", String.class,int.class); method.invoke(demo.newInstance(),"Rollen",20); }catch (Exception e) { e.printStackTrace(); } } }【运行结果】:
hello ,china
Rollen 20
【案例】调用其他类的set和get方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
class hello { public static void main(String[] args) { Class<?> demo = null; Object obj=null; try { demo = Class.forName("Reflect.Person"); } catch (Exception e) { e.printStackTrace(); } try{ obj=demo.newInstance(); }catch (Exception e) { e.printStackTrace(); } setter(obj,"Sex","男",String.class); getter(obj,"Sex"); } /** * @param obj * 操作的对象 * @param att * 操作的属性 * */ public static void getter(Object obj, String att) { try { Method method = obj.getClass().getMethod("get" + att); System.out.println(method.invoke(obj)); } catch (Exception e) { e.printStackTrace(); } } /** * @param obj * 操作的对象 * @param att * 操作的属性 * @param value * 设置的值 * @param type * 参数的属性 * */ public static void setter(Object obj, String att, Object value, Class<?> type) { try { Method method = obj.getClass().getMethod("set" + att, type); method.invoke(obj, value); } catch (Exception e) { e.printStackTrace(); } } }// end class |
【运行结果】:
男
【案例】通过反射操作属性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class hello { public static void main(String[] args) throws Exception { Class<?> demo = null; Object obj = null; demo = Class.forName("Reflect.Person"); obj = demo.newInstance(); Field field = demo.getDeclaredField("sex"); field.setAccessible(true); field.set(obj, "男"); System.out.println(field.get(obj)); } }// end class |
【案例】通过反射取得并修改数组的信息:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.lang.reflect.*; class hello{ public static void main(String[] args) { int[] temp={1,2,3,4,5}; Class<?>demo=temp.getClass().getComponentType(); System.out.println("数组类型: "+demo.getName()); System.out.println("数组长度 "+Array.getLength(temp)); System.out.println("数组的第一个元素: "+Array.get(temp, 0)); Array.set(temp, 0, 100); System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0)); } } |
【运行结果】:
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100
【案例】通过反射修改数组大小
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class hello{ public static void main(String[] args) { int[] temp={1,2,3,4,5,6,7,8,9}; int[] newTemp=(int[])arrayInc(temp,15); print(newTemp); System.out.println("====================="); String[] atr={"a","b","c"}; String[] str1=(String[])arrayInc(atr,8); print(str1); } /** * 修改数组大小 * */ public static Object arrayInc(Object obj,int len){ Class<?>arr=obj.getClass().getComponentType(); Object newArr=Array.newInstance(arr, len); int co=Array.getLength(obj); System.arraycopy(obj, 0, newArr, 0, co); return newArr; } /** * 打印 * */ public static void print(Object obj){ Class<?>c=obj.getClass(); if(!c.isArray()){ return; } System.out.println("数组长度为: "+Array.getLength(obj)); for (int i = 0; i < Array.getLength(obj); i++) { System.out.print(Array.get(obj, i)+" "); } } } |
【运行结果】:
数组长度为: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
数组长度为: 8
a b c null null null null null
动态代理
【案例】首先来看看如何获得类加载器:
|
1
2
3
4
5
6
7
8
9
|
class test{ } class hello{ public static void main(String[] args) { test t=new test(); System.out.println("类加载器 "+t.getClass().getClassLoader().getClass().getName()); } } |
【程序输出】:
类加载器 sun.misc.Launcher$AppClassLoader
其实在java中有三种类类加载器。
1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package Reflect; import java.lang.reflect.*; //定义项目接口 interface Subject { public String say(String name, int age); } // 定义真实项目 class RealSubject implements Subject { @Override public String say(String name, int age) { return name + " " + age; } } class MyInvocationHandler implements InvocationHandler { private Object obj = null; public Object bind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke(this.obj, args); return temp; } } class hello { public static void main(String[] args) { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind(new RealSubject()); String info = sub.say("Rollen", 20); System.out.println(info); } } |
【运行结果】:
Rollen 20
类的生命周期
在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。
类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。但是同一个类只会被类装载器装载以前
链接就是把二进制数据组装为可以运行的状态。
链接分为校验,准备,解析这3个阶段
校验一般用来确认此二进制文件是否适合当前的JVM(版本),
准备就是为静态成员分配内存空间,。并设置默认值
解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)
完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。
当没有任何引用指向Class对象时就会被卸载,结束类的生命周期
将反射用于工厂模式
先来看看,如果不用反射的时候,的工厂模式吧:
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/** * @author Rollen-Holt 设计模式之 工厂模式 */ interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } // 构造工厂类 // 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了 class Factory{ public static fruit getInstance(String fruitName){ fruit f=null; if("Apple".equals(fruitName)){ f=new Apple(); } if("Orange".equals(fruitName)){ f=new Orange(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance("Orange"); f.eat(); } } |
这样,当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。
现在我们看看利用反射机制:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package Reflect; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } class Factory{ public static fruit getInstance(String ClassName){ fruit f=null; try{ f=(fruit)Class.forName(ClassName).newInstance(); }catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance("Reflect.Apple"); if(f!=null){ f.eat(); } } } |
现在就算我们添加任意多个子类的时候,工厂类就不需要修改。
上面的爱吗虽然可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。
下面我们来看看: 结合属性文件的工厂模式
首先创建一个fruit.properties的资源文件,
内容为:
|
1
2
|
apple=Reflect.Apple orange=Reflect.Orange |
然后编写主类代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package Reflect; import java.io.*; import java.util.*; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } //操作属性文件类 class init{ public static Properties getPro() throws FileNotFoundException, IOException{ Properties pro=new Properties(); File f=new File("fruit.properties"); if(f.exists()){ pro.load(new FileInputStream(f)); }else{ pro.setProperty("apple", "Reflect.Apple"); pro.setProperty("orange", "Reflect.Orange"); pro.store(new FileOutputStream(f), "FRUIT CLASS"); } return pro; } } class Factory{ public static fruit getInstance(String ClassName){ fruit f=null; try{ f=(fruit)Class.forName(ClassName).newInstance(); }catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a) throws FileNotFoundException, IOException{ Properties pro=init.getPro(); fruit f=Factory.getInstance(pro.getProperty("apple")); if(f!=null){ f.eat(); } } } |
【运行结果】:Apple
Java Reflect的更多相关文章
- java reflect 初始学习 动态加载类
首先要理解Class类: 在java 的反射中,Class.forName("com.lilin.Office") 使用类的全名,这样获取,不仅仅表示了类的类类型,同时还代表着类的 ...
- Java反射学习(java reflect)(二)
ok之前说了Java的反射和反射分析类,那这些东西有神马作用呢,下面就来说应用: 三.运行时使用反射分析对象 简单写一个Employee类,然后利用JAVA反射去取name域,getDeclareFi ...
- Java反射学习(java reflect)(一)
具有能够分析类能力的程序被称为反射,使用反射库可以编写能够动态操纵Java代码的程序. 一.开始 背景:Java运行时系统始终对所有对象维护一个被称为Runtime的类型标识,然后这货save着每个对 ...
- java reflect反思总结
--------------TestBean package lh.demo.bean; public class TestBean { private String userName; priv ...
- java reflect反射调用方法invoke
类定义 package Reflect; public class MyTest { public int a; public static int b; public static final in ...
- java reflect反射获取方法变量参数
类的成员包含变量(Field),方法(Method),构造器(Constructor) 类定义 package Reflect; public class MyTest { public int a; ...
- Java reflect 反射学习笔记
1. class 类的使用 万事万物皆对象 (基本数据类型, 静态成员不是面向对象), 所以我们创建的每一个类都是对象, 即类本身是java.lang.Class类的实例对象, 但是这些对象不需要 n ...
- java reflect反射---Java高级开发必须懂的
理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底层的操作会很有帮助. 一.Class类的使用 1.万事万物皆对象,( ...
- Java —— Reflect反射机制
JAVA反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java的反射机制. ...
随机推荐
- Devexpress WPF教程
[视频专辑]酷炫界面开发神器DevExpress WPF视频教程(36集全) http://www.devexpresscn.com/post/620.html
- UDP通讯
上一篇有说到TCP通讯,这篇来谈谈UDP通讯方式 基于Udp协议是无连接模式通讯,占用资源少,响应速度快,延时低.至于可靠性,可通过应用层的控制来满足.(不可靠连接) (1).建立一个套接字(Sock ...
- ceph pg_num 数值计算
通常在创建pool之前,需要覆盖默认的pg_num,官方推荐: 若少于5个OSD, 设置pg_num为128. 5~10个OSD,设置pg_num为512. 10~50个OSD,设置pg_num为40 ...
- VS2013如何添加LIb库及头文件的步骤
在VS工程中,添加c/c++工程中外部头文件及库的基本步骤: 1.添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录. 2.添加文件引用 ...
- WebService-php- 2(17)
wsdl实例 <?xml version ='1.0' encoding ='UTF-8' ?> <definitions targetNamespace='http://local ...
- 【文文殿下】Manache算法-学习笔记
Manache算法 定义:是一个判断回文子串的算法,我们结合例题解释: 题目:给定一个长度为 n 的字符串 S,求其最长回文子串 一个字符串是回文的,当且仅当反转后的串与原串完全相等 分析:对于这个题 ...
- abstract方法必须在abstract类中 这句话是对的还是错的?
对 参考文章:https://zhidao.baidu.com/question/435526297.html interface中所有的方法都是抽象的,抽象类中部分方法是抽象的 实现interfac ...
- 任意模数NTT和FFT的玄学优化学习笔记
本来一直都是写\(7\)次的\(MTT\)的--然后被\(shadowice\)巨巨调教了一通之后只好去学一下\(4\)次的了-- 简单来说就是我们现在需要处理一类模数不为\(NTT\)模数的情况 这 ...
- PHP中php_sapi_name()与array_map()
1,php_sapi_name() php_sapi_name返回web服务器和php之间的接口类型.函数说明: string php_sapi_name(void) 返回描述php所使用的接口类型的 ...
- [JS] jq绑定事件的参数传递
$(function(){ var obj = {name:"select",param:"2"}; $("#select").click( ...