黑马程序员技术交流社区
标题: 笔记之---java反射(码了好几天拉) [打印本页]
作者: 小僧玄奘 时间: 2015-1-5 18:25
标题: 笔记之---java反射(码了好几天拉)
///小僧玄奘 -----HM-----TEST实例
///1个mian方法类,1个测试反射的类,1个测试反射的类实现的接口。
/// 排版已经过处理,可直接复制代码测试。注意先建reflection包。在此包下建类并copy代码测试
//什么是反射:要让java程序运行,就需要让java类被java虚拟机加载。我们的程序
// 都是在编译期的时候就已经知道所需要的哪些类已经被加载了
// 而反射的特点是在程序运行的时候动态加载一个类,并且可以调用该类方法和属性,包括私有属性
//
// 反射的作用:程序运行的时候动态加载一个类,并且可以调用该类方法和属性,包括私有属性
//
// 应用场景之1:
// 比如简单工厂模式,是根据传入子类名称的字符串来判断 new出相应的子类
// 这样增加一个子类就需要修改工厂代码
// 如果用到反射则不需要再修改工厂代码了,只需要增加相应的子类即可
//测试需要被反射的类
package reflection;
public class TestReflection implements reflection.TestReflectionInterFace {
public TestReflection(){
}
public TestReflection(String name,int i){
this.name=name;
this.a=i;
}
public TestReflection(String name){
this.name=name;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
private String name;
private int a;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void getStr(){
System.out.println("此方法getStr被调用");
}
public void test(String name,int i){
System.out.println("此方法test被调用"+name+i);
}
//接口函数
public void TestReflectionInterFace() {
// TODO Auto-generated method stub
System.out.println("hello,this is InterFace");
}
public void TestReflectionInterFace(String name, int age) {
// TODO Auto-generated method stub
System.out.println(name+age);
}
}
//测试需要被反射的类实现的接口
package reflection;
public interface TestReflectionInterFace {
public static String name="DA";
public static int age=18;
public void TestReflectionInterFace();
public void TestReflectionInterFace(String name,int age);
}
//mian方法
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchMethodException {
// TODO Auto-generated method stub
Class demo=null;
demo=Class.forName("reflection.TestReflection");
System.out.println("----------本类属性---------------");
//取得本类的所有属性
Field[] field=demo.getDeclaredFields();
for(int i=0;i<field.length;i++){
//获得权限修饰符
int mo=field.getModifiers();
String priv =Modifier.toString(mo);
//获得属性类型
Class<?> type=field.getType();
System.out.println(priv+" "+type.getName()+" "+field.getName()+";");
}
System.out.println("----------实现的接口或父类的属性----------");
//获取指定类的父类
Class superClass=demo.getSuperclass();
String superName=superClass.getName();
System.out.println("父类是:"+superName);
//获取指定类的接口
Class[] intfaces= demo.getInterfaces();
for(Class c:intfaces){
System.out.println("接口是:"+ c.getName());
}
//取得实现的接口或父类的属性
Field[] field1=demo.getFields();
for(int i=0;i<field1.length;i++){
//获得修饰符
int mo=field1.getModifiers();
String priv=Modifier.toString(mo);
//获得属性类型
Class type=field1.getType();
System.out.println("父类或接口属性:"+priv+" "+type.getCanonicalName()+" "
+field.getName());
}
//反射调用方法
Method [] metd=demo.getDeclaredMethods();//获得方法
for(Method met:metd){//返回包括属性封装方法成员方法
Class[] paramTypes = met.getParameterTypes();
String a=Modifier.toString(met.getModifiers()); //获取方法修饰符
a+= " "+ met.getReturnType(); //获取方法返回类型
a+= " "+met.getName()+"("; //获取方法名
for (int i = 0; i < paramTypes.length; i++) {
a+=paramTypes.getName();//获得参数
if (paramTypes.length > 1) {
if((i+1)!=paramTypes.length){//因为数组下标从0开始,所以循环i+1=paramTypes.length就表示后面没有参数了
a+=",";
}
}
}
a+=")";
System.out.println(a);//打印拼接的字符串
}
//反射调用方法
//调用无参方法
Method method=demo.getMethod("getStr");
method.invoke(demo. newInstance());
//调用带参方法
method=demo.getMethod("test", String.class,int.class);
method.invoke(demo.newInstance(),"test",1);
}
}
打印结果:
----------本类属性---------------
private java.lang.String name;
private int a;
----------实现的接口或父类的属性----------
父类是:java.lang.Object
接口是:reflection.TestReflectionInterFace
父类或接口属性:public static final java.lang.String name
父类或接口属性:public static final int a
public class java.lang.String getName()
public void setName(java.lang.String)
public void getStr()
public void test(java.lang.String,int)
public int getA()
public void setA()
public void TestReflectionInterFace(java.lang.String,int)
public void TestReflectionInterFace()
此方法getStr被调用
此方法test被调用test1
public void TestReflectionInterFace(java.lang.String,int)
public void TestReflectionInterFace()
此方法getStr被调用
作者: 小僧玄奘 时间: 2015-1-5 18:26
/*如果是静态方法invoke第1个参数传null,因为静态方法是类方法不需要传对象实例去运行
* method实例是一个代理实例,调用这个实例的任何方法都相当于调用invoke方法
* 被转成invoke方法,invoke回调(反转,反射),也就是动态代理
* 最简单的用法是可以把方法参数化
* 比如你Test类里有一系列名字相似的方法setValue1、setValue2等等
* 可以把方法名存进数组v[],然后循环里invoke(test,v[i]),就顺序调用了全部setValue
*/
/*
* Java类反射中所必须的类:
* Java的类反射所需要的类并不多,它们分别是:Field、Constructor、Method、Class、Object,下面我将对这些类做一个简单的说明。
* Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
* Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
* Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
* Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
* Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
*/
作者: kerner 时间: 2015-1-5 21:50
谢谢楼主分享的笔记。
作者: 小僧玄奘 时间: 2015-1-5 21:51
:L为什么后面的字歪了
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |