Java反射机制研究
来源:互联网 发布:unity3d抗锯齿设置 编辑:程序博客网 时间:2024/05/21 10:58
以前听同时说反射很强大,看了一些相关文章今天把反射总结一下。
说明:反射主要用于开发框架,即制作框架;
一、获得Class对象
Class<?> c = Class.forName("classname"); 抛出ClassNotFoundException
二、获得实现接口
Class<?> inters[] = c.getInterfaces();
for(int i=0;i<inters.length;i++){
System.out.print(inters[i].getName()+" "); //getName()方法为取得接口名称;
}
三、获得父类
Class<?> superClass = c.getSuperclass(); //获得父类
String name = superClass.getName(); //获得父类名称
四、取得构造方法
Constructor cons[] = c.getConstructors(); //获得公开的构造方法
Constructor dcons[] = c.getDeclaredConstructors(); //获得全部构造方法
String modifier = Modifier.toString(cons[i].getModifiers()); //获得访问权限
String name = cons[i].getName(); //获得构造方法名称
Class<?> params[] = cons[i].getParameterTypes(); //获得参数类型对象
五、获得Method
Method ms[] = c.getMethods(); //返回公共的全部方法,包括继承方法
Method dms[] = c.getDeclaredMethods(); //返回本类全部方法,不包括继承的方法
Class<?> rt = ms[i].getReturnType();
Class<?>params[] = ms[i].getParameterTypes();
String name = ms[i].getName();
String modifier = Modifier.toString(ms[i].getModifiers());
Class<?>ex[] = ms[i].getExceptionTypes(); //获得异常
String name = ex[i].getName(); //获得异常名称
六、获得Field
Field fs[] = c.getFields(); //获得公共属性,包括继承属性
Field dfs[] = c.getDeclaredFields(); // 获得本类全部属性
Class<?> type = fs[i].getType(); //获得属性的类型对象
String name = fs[i].getName(); //获得属性的名称
String modifier = Modifier.toString(fs[i].getModifiers());
七、通过反射创建一个对象
(1)
Class<?> c = Class.forName("Person");
Person p = (Person)c.newInstance();
(2)
Constructor con = c1.getConstructor(Class....param);
Object obj = con.newInstance(Object obj); //根据构造函数创建一个实例
八、Constructor创建对象
Class c = Class.forName("Person");
Constructor<?> cons[] = c.getConstructors();
Person p = (Person)cons[0].newInstance("xiazdong",15);
注:如果调用的构造函数为私有,则需要c.setAccessible(true);
九、调用特定方法
Method m = c1.getMethod("funcname",Class<?>...c); //funcname表示调用方法的名称,c表示参数的Class对象
例如:Method m = c1.getMethod("fun",String.class,int.class); 表示调用fun(String,int);函数
Object obj = m.invoke(c1.newInstance(),"xiazdong",20); //如果有返回值,则invoke函数返回;
注:如果是调用静态的方法,则不需要设置对象;
Object obj = m.invoke(null,"xiazdong");
注:如果参数中有数组,比如 public static void main(String[]args);
则
Method m = c1.getMethod("main",String[].class);
m.invoke(null,(Object)new String[]{"aa","bb"});是对的;
m.invoke(null,new String[]{"aa","bb"}); 会调用 main(String,String);函数;
十、调用特定属性
Field f = c1.getDeclaredField("name"); //返回name属性
f.setAccessible(true); //私有属性可见
String name = (String)f.get(Object obj); //返回obj对象的name属性的值
f.set(Object obj,String n); //设置obj对象的name属性为n值;
十一、操作数组
int tmp[] = {1,2,3};
Class<?> c = tmp.getClass().getComponentType();
Array.getLength(tmp); //tmp数组的长度
c.getName(); //获得数组类型名称
Array.get(Object obj,int index); //获得obj数组的index索引的数值
Array.set(Object obj,int index,VALUE); //设置obj数组的index索引的数值为value;
Object obj = Array.newInstance(c,length); //c为数组的类型,length为数组的长度;obj为返回的数组对象;
示例:
import java.lang.reflect.*;public class GetMethodDemo01{public static void main(String args[])throws Exception{Class<?> c1 = Class.forName("Person");Method m = c1.getMethod("sayHello");m.invoke(c1.newInstance());Method m2 = c1.getMethod("sayHello2",String.class,int.class);String str = (String)m2.invoke(c1.newInstance(),"xiazdong",123);System.out.println(str);Field nameField = c1.getDeclaredField("name");Field ageField = c1.getDeclaredField("age");nameField.setAccessible(true);ageField.setAccessible(true);Person obj = (Person)c1.newInstance();obj.setName("xzdong");obj.setAge(12);System.out.println(nameField.get(obj));System.out.println(ageField.get(obj));Method setName = c1.getMethod("setName",String.class);setName.invoke(obj,"changed");Method getName = c1.getMethod("getName");System.out.println(getName.invoke(obj));int tmp[] = {1,2,3};Class<?> c3 = tmp.getClass().getComponentType();System.out.println(c3.getName());System.out.println("第一个数:"+Array.get(tmp,0));Array.set(tmp,0,5);System.out.println("第一个数:"+Array.get(tmp,0));Object arr = Array.newInstance(c3,5);System.arraycopy(tmp,0,arr,0,Array.getLength(tmp));System.out.println(Array.get(arr,2));System.out.println(Array.get(arr,3));}}
import java.lang.reflect.*;interface China{public static final String NAME = "CHINA";public int AGE = 60;public void sayHello();public String sayHello2(String name,int age);}class Person implements China{private String name;private int 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;}public void sayHello(){System.out.println(NAME+" "+AGE);}public String sayHello2(String name,int age){return name+" "+age;}}
十一、工厂设计模式
1.最简单的工厂设计模式
场景:有一个Fruit接口,Apple类和Orange类都实现了Fruit接口,Factory用来生产水果;
import java.io.*;import java.util.*;interface Fruit{public void eat();}class Apple implements Fruit{public void eat(){System.out.println("吃苹果");}}class Orange implements Fruit{public void eat(){System.out.println("吃橘子");}}class Factory{public static Fruit getInstance(String name)throws Exception{Fruit f = null;if("apple".equals(name)){f = new Apple();}else if("orange".equals(name)){f = new Orange();}if(f!=null){return f;}else return null;}}public class FactoryDemo01{public static void main(String args[])throws Exception{Fruit f = Factory.getInstance("apple");f.eat();}}
2.通过反射实现
上面的例子有一个坏处,就是在Factory的getInstance代码会随着水果数量增加而增加,比如如果增加了一个banana类,则需要添加
if(name.equals("banana")){...}
这样非常不方便,因此反射就是一个很好的解决方法:
import java.io.*;import java.util.*;interface Fruit{public void eat();}class Apple implements Fruit{public void eat(){System.out.println("吃苹果");}}class Orange implements Fruit{public void eat(){System.out.println("吃橘子");}}class Factory{public static Fruit getInstance(String name)throws Exception{Fruit f = nullFruit f = (Fruit)Class.forName(name).newInstance();if(f!=null){return f;}else return null;}}public class FactoryDemo01{public static void main(String args[])throws Exception{Fruit f = Factory.getInstance("Apple");f.eat();}}3.增加灵活性:配置文件
但是还有一个缺点,就是如果Apple类等有包名,则如果要访问此类,必须添加包名+类名称才可以。比如Apple类的最上方:package org;则必须通过org.Apple才可以访问Apple类。因此通过Properties文件可以解决这个问题;
import java.io.*;import java.util.*;interface Fruit{public void eat();}class Apple implements Fruit{public void eat(){System.out.println("吃苹果");}}class Orange implements Fruit{public void eat(){System.out.println("吃橘子");}}class Factory{public static Fruit getInstance(String name)throws Exception{Fruit f = nullFruit f = (Fruit)Class.forName(name).newInstance();if(f!=null){return f;}else return null;} private Factory(){}}public class FactoryDemo01{public static void main(String args[])throws Exception{Properties p = new Properties();p.load(new FileInputStream("1.properties"));String str = p.getProperty("apple");Fruit f = Factory.getInstance(str);f.eat();}}
1.properties代码:
apple=Apple
orange=Orange
- Java反射机制研究
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java反射机制深入研究
- Java 反射机制深入研究
- Java反射机制深入研究
- java反射机制深入研究
- Java反射机制深入研究
- WCF学习笔记—Overview
- 2015腾讯软开类笔试题(回忆版)
- 数据挖掘、数据分析、海量数据处理的面试题(总结july的博客)
- 编写函数求两个整数 a 和 b 之间的较大值。要求不能使用if, while, switch, for, ?: 以及任何的比较语句
- cadence16.5中总线拓扑的设置方法
- Java反射机制研究
- 抢占式任务调度和非抢占式(轮询任务调度)的区别,以及任务调度算法的用途。
- cadence16.5中XNET的设置方法
- cadence16.5中区域约束规则的设置
- C#中的Parse转换和Convert转换
- 最简单的shell程序——yash
- 如何重装系统以及锐捷V1.61在win7上无法运行的问题
- uva519Puzzle (II)
- cadence16.5中走线长度设置方法