文档章节

什么时候Java反射

踏破铁鞋无觅处
 踏破铁鞋无觅处
发布于 2018/08/16 01:33
字数 2078
阅读 34
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

写的不是很详细,可能会有看不懂的地方,建议去慕课网的视频:https://www.imooc.com/video/3735

以前就学习过java的反射,但是后来一直没有用过,现在回过头来看了一下,并把知识点做了整理

  • Class类

1)在面向对象的世界里,万事万物皆对象。
   类也是对象,类是java.lang.Class类的实例对象。
   官方文档是这么解释的There is a class named Class
2)Foo的实例对象
   Foo foo1=new Foo();
   //Foo类是java.lang.Class类的实例对象,也有构造方法(本地方法),但是不能使用new
   
   //三种表示方式
   //第一种表示方式--->说明任何一个类都有一个隐含的静态成员变量class
     Class c1=Foo.class; 
   //第二种表达方式--->已经有该类的对象通过getClass()方法
     Class c2=foo1.getClass();
   //第三种表达方式
     Class c3=Class.forName("com.Foo");
   //通过c1 or c2 or c3(类类型)创建Foo的实例对象(需要用try catch包住)
     Foo foo=(Foo)c1.newInstance();//需要有无参数的构造方法

在这里可以看到Class的构造方法,是本地方法,只能由虚拟机创建,并且由c语言实现

c1,c2,c3表示了Foo类的类类型(class type)
一个类是Class类的一个实例对象(c1==c2==c3)返回true
创建实例对象:c1.newInstance();

  • Java 动态加载类

这一部分使用ide工具是看不出来的,最好使用Sublime类似的工具,首先添加.java文件,后使用javac对文件进行编译,使用java运行编译后的文件看是否出错

定义office类,静态加载类
public class office(){
   public static void main(String[] args){
      if("word".equals(args[0])){
        Word word=new Word();
     }
      if("excel".equals(args[0])){
        Excel excel=new Excel();
     }
  }
}
javac office.java就会直接报错,因为Word和Excel类没有实现
new创建对象:静态加载类,在编译时刻就加载所有的【可能用到的类】。任何一个使用的类有问题,都不能通过编译,都会报错。
在上面的例子中用到了:new Word();new Excel();需要静态加载Word、Excel类,编译时刻就会对类Word和Excel进行加载,如果(任一)类文件中有错误就会编译不通过。

定义office2类,动态加载类
public class office2(){
   public static void main(String[] args){

     if("Word".equals(args[0])){
       Class class=Class.forName(args[0]);
       Word word=(Word)class.newInstace();
     }
      if("Excel".equals(args[0])){
        Class class=Class.forName(args[0]);
        Excel excel=(Excel)class.newInstace();
     }
  }
}
并且还有Word类
public class Word(){
   public Word(){}   
}
javac office2.java,编译没问题
java office2 Word,运行没问题
java office2 Excel,运行出错
Class.forName():动态加载类,运行时刻进行加载。
如果名称为args[0]的类不存在,编译时刻没问题,但是运行会报错。这就是为何有时候会出现编译通过,运行报错的原因。
动态加载一个好处,就是可以随时增加需要编译的类。例如没有Excel类,只有Word类,也可以运行,需要Excel类时再由程序员写此类

(为了能统一控制,Word类、Excel类需要继承同一个父类或者继承同一个接口)。

public Interface Micro(){}
public class Word implements Micro(){}
public class Excel implements Micro(){}
public class Test(){
   public static void main(String[] args){

        Class class=Class.forName(args[0]);
        Micro micro=(Micro)class.newInstace();
        //这里的micro会根据args[0]的值来确定是哪一个实现类(子类)的对象啊
  }
}

new创建对象,编译时刻(javac)加载类,Class.forName("");运行时刻(java)加载类

理解了为什么有时候会出现编译通过,运行报错的原因。(因为使用了动态加载类)

  •  Java 获取方法信息


    public static void pringClassMessage(Object object) {
        //要获取类的信息,首先要获取类的类型
        Class c = object.getClass();
        //获取类的名称
        System.out.println("类的名称是:" + c.getName());
        /*
        * Method类,方法对象
        * 一个成员方法就是一个Method对象
        * getMethods()方法获取的是所有public函数,包括父类继承而来的
        * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
        * */
        Method[] ms = c.getMethods();//c.getDeclaredMethods();
        for (int i = 0; i < ms.length; i++) {
            //得到方法的返回值类型的类类型
            Class returnType = ms[i].getReturnType();
            System.out.println(returnType.getName());
            //得到方法名
            System.out.println(ms[i].getName() + "(");
            //获取参数类型-->得到的是参数列表的类型的类类型
            Class[] paramType = ms[i].getParameterTypes();
            for (Class class1 : paramType) {
                System.out.println(class1.getName() + ",");
            }
            System.out.println(")");
        }
    }
}

java的方法也是类对象,是java.lang.refelect.Method的对象

通过下面两个方法,可以获得类类型是c1的类的方法数组

c1.getMethod();

c1.getDeclareMethod();

返回值的类类型

m[0].getReturnType();

参数的类类型数组

m[0].getParameterTypes();

  • Java 获取成员变量

Java反射机制——获取成员变量
成员变量是java.lang.reflect.Field的对象
1、Field类封装了关于成员变量的操作
2、Field[] fs = c.getFields()方法获取所有public的成员变量Field[]信息
3、c.getDeclaredFields获取的是该类自己声明的成员变量信息
4、field.getType()获得成员类型的类类型
5、field.getName()获得成员的名称

类的成员变量是java.lang.reflect.Field的对象

c1.getField();

c1.getDeclareField();

成员变量的类类型

f[0].getType();

成员变量的名称

f[0].getName();

  • Java 获取构造函数信息

Java反射机制——获取构造函数
构造函数是java.lang.Constructor类的对象
1、通过Class.getConstructor()获得Constructor[]所有公有构造方法信息
2、建议getDeclaredConstructors()获取自己声明的构造方法
3、Constructor.getName():String
4、Constructor.getParameterTypes():Class[]
  •  Java 方法反射的基本操作

方法的反射:
1.获取A类中的print(int,int)方法:
 //要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
  A a1=new A();
  Class c= a1.getClass();
 //获取方法 由名称和参数列表来决定,getMethod获取的是public方法,getDelcaredMethod获取自己声明的方法
  Method m =c.getMethod(methodName,paramtypes);//paramtypes可以用数组的形式  表示new Class[]{int.class,int.class},也可以直接列举类类型
2.方法的反射操作:是用m对象来进行方法调用,和a1.print(10,20)调用的方法相同 m.invoke(a1,new Object[]{10,20})
  Object o=m.invoke(对象名,参数);//方法如果没有返回值返回null,如果有返回值返回具体值,参数可用数组的方式表示,也可以直接列举,没有参数就不写

public Class A{
 public void print(){};
 public void Print(Sting a,String b){}
 public void Print(int a,int b){};
} 
public Class B{
 public static void main(String[] args){
  A a1 = new A();  
  Class c= a1.getclass;
  Method getMet=c.getMethod("print",String.class,String.class);//忘了加引号
  Object obj=getMet.invoke(a1,"df","df");
}
}

获取方法

c1.getMethod("方法名",Class[]);

调用方法

m.invoke(c1,参数);

  • Java 通过反射了解集合泛型的本质

Java反射机制——通过反射了解集合泛型的本质
1:反射的操作都是编译之后的操作;就是运行阶段
2:java中集合的泛型是防止错误输入的;只在编译阶段有效,只要绕过编译就无效啦
我们可以通过方法的反射来操作,绕过编译

ArrayList list1=new ArrayList();
ArrayList<String> list2=new ArrayList<String>();
Class c1=list1.getClass();
Class c2=list2.getClass();
System.out.print(c1==c2);   //true
Method m=c2.getMethod("add",Object.class);
m.invoke(list2,20);         //向list2集合中添加一个int 型的值,绕过编译
当然是不能直接foreach list2集合的,会报类型转换错误

1:反射的操作都是编译之后的操作
2:java中集合的泛型是防止错误输入的;只在编译阶段有效,只要绕过编译就无效啦,我们可以通过方法的反射来操作,绕过编译

 

总结一下

反射是运行阶段处理的,绕过了编译,所以好多东西编译阶段是不处理的

个人开发中反射用到的会比较少,具体会不会用也要看需求,功能主要就是根据一个String来得到你要的实体对象,然后调用它包含的东西。

但是如果是要自己写框架的话,那就会用得比较多了。

 

 

 

 

上一篇: 二进制
踏破铁鞋无觅处

踏破铁鞋无觅处

粉丝 6
博文 113
码字总数 35886
作品 0
海淀
程序员
私信 提问
加载中
请先登录后再评论。
研究虚拟机--Jikes RVM

Jikes研究虚拟机(Jikes Research Virtual Machine,简称Jikes RVM)是一种成熟的用于执行Java程序的虚拟机,其早期版本与当前版本分别在通用公共许可证(CPL)与Eclipse公共许可证(EPL)下开...

匿名
2013/02/13
1.1K
0
Swing界面分析和调试工具--Swing Inspector

Swing Inspector是一个Java Swing/AWT用户界面分析和调试工具,功能与firebug类似,具有强大的Swing/AWT用户界面分析和调试相关功能。 适用于从java swing初级到高级的所有开发人员,能够快速...

匿名
2013/03/06
3.4K
0
Java™ 编译器--Janino

Janino是一个超级小但又超级快的Java™ 编译器. 它不仅能像javac工具那样讲一组源文件编译成字节码文件,还可以对一些Java表达式,代码块,类中的文本(class body)或者内存中源文件进行编译,...

匿名
2013/04/02
4.1K
0
高效 Java Web 开发框架--JessMA

JessMA 是功能完备的高性能 Full-Stack Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 数据库访问组件(内部已提供了 Hibernate、MyBatis 与 JDBC DAO 组件),集成了 Action 拦截...

伤神小怪兽
2012/11/13
9.2K
3
代替Java Web Start--Getdown

Getdown 是一个Java程序部署工具,类似Java Web Start,但是避免了一些Java Web Start的限制,它可以自动把Java程序及相关资源下载和安装到客户的电脑上,当服务器上有新版本是能够自动升级。...

匿名
2012/12/03
616
0

没有更多内容

加载失败,请刷新页面

加载更多

PPDet:减少Anchor-free目标检测中的标签噪声,小目标检测提升明显

本文转载自AI算法修炼营。 这篇文章收录于BMVC2020,主要的思想是减少anchor-free目标检测中的label噪声,在COCO小目标检测上表现SOTA!性能优于FreeAnchor、CenterNet和FCOS等网络。整体思路...

我爱计算机视觉
昨天
0
0
BIO、NIO、AIO 区别和应用场景

点击上方“ java1234 ”,选择“标星公众号” 优质文章,第一时间送达 66套java从入门到精通实战课程分享...

小锋2
今天
0
0
ContentProvider(查询 插入 修改 删除 )

注意 本篇实在sqlite的基础上编写的所以建议首先了解sqlite 首先建立两个模块 ContentProvider ContentResolver ContentProvider 里面需要建立表和建立连接 所以在这里需要建立DBHelp类 DBHe...

osc_6ttvlt1w
29分钟前
30
0
用这个网站一查,才知道自己被卖了

还记得上个月好多大佬的Twitter账号被盗用于网络诈骗的事件吗。 7月15日,美国前总统奥巴马、“股神”巴菲特、特斯拉CEO马斯克、微软创始人比尔·盖茨等人的账户连续“被登录”,用来向大众诈...

猿大白
今天
11
0
牛客多校第9场E Groundhog Chasing Death

开始以为是什么高深的数论题,后来 重新 推了一下,得到了个这么个式子。 ∏ i = a b ∏ j = c d ( p 1 m i n ( a 1 [ 1 ] i , a 2 [ 1 ] j ) p 2 m i n ( a 1 [ 2 ] i , a 2 [ 2 ] j ) . . ...

osc_wdq5dwoy
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部