浅谈java中的反射

引言:java的高级特性-反射一直是困扰自己的一个很大问题,今天专门花了半天再将java中的反射看了一遍,下面简单谈谈自己对反射的理解,以及它的具体用法:

一:什么是反射?

  • 在java核心编程中是这样定义的:能够分析类能力的程序
public class fruit{
  private String name;
  public fruit(String name){
    this.name  = name;
  }
  public void getName(){
    return name;
  }
  public String setName(String name){
    this.name = name;
  }
  public static void main(String[] args){
    fruit  apple =new fruit();
    apple.getName();
  }
}

按照Java创建对象的正常逻辑,如上面的代码所示,我们一般都是根据具体的类fruit来创建对象apple,然后在利用我们所创建的对象去调用方法;apple.getName();而java中的反射的流程则相反是根据具体的对象去获取相关的类Class的信息,

二:反射的作用:

  • <1>:可以在程序运行过程中分析类的能力
  • <2>:在运行中查看对象,例如编写一个toString方法供所有类使用
  • <3>:实现数组的操作代码
  • <4>:利用Method对象;

三:具体怎么使用:

补充知识:我们都知道,编写java程序时我们所编写的文件是一个名为xxx.java的文件,通过java编译器编译之后会成为一个.class文件;这时再通过JVM的类加载器加载到JVM的运行时数据区里面的方法区(.class)文件,所谓方法区里面保存的类的相关信息就是指这一过程的产生的class对象;
java程序在运行过程中会为每一对象保存一个Class对象,用来保存该对象和类的一些相关信息;比如:方法,属性,构造函数等;所以想要使用反射我们首先要做的就是拿到Class对象;

  • <1>:拿到Class对象:
    有三种方法:
  • A:根据对象获取的getClass()方法:
Class cls = apple.getClass();

B:根据类的class属性获取

Class cls = fruit.class;

C:根据Class类的静态方法forName("类的完整路径")

Class cls = Class.forName("Chapter1.fruit")

具体采用那一种,大家可以根据具体情况具体分析;

  • <2>:根据拿到的Class对象创建我们所需的对象:
fruit orange = (fruit)cls.newInstance();//注意该方法返回的Object对
象,所以我们需要强制类型转换;

这里创建对象调用的是fruit类中的默认的构造方法,如果没有默认构造方法此项操作将会报错已检查异常(即运行时会报错);
所以我们调用此方法时一定要保证目标类有默认的构造方法;

  • <3>:获取调用构造方法:
Constructor con = cls.getConstructor(Class<?>... parameterTypes)//返回指定采参数类型的构造方法;注意参数一定要传递Class对象哦!
Constructor[] con = cls.getConstructors();//返回所有的共有构造器:构造方法数组;
Constructor[] con = cls.getDeclaredConstructors();//返回所有的构造器:构造方法数组;
Constructor con = cls.getDeclaredConstructor(Class<?>... parameterTypes);//返回指定的构造器:构造方法数组;
//在拿到对应的都早方法之后我们就可以根据指定构造方法创建对象
Constructor cons = cls.getConstructor(String.class);
fruit f  = cons.newInstance("陈鹏");
  • <4>:获得调用普通方法
Method[] methods = cls.getMethods();//返回该类中以及其超类中所有的的公有的方法
Method[] methods = cls.getDeclaredMethods();//返回该类中所有的的公有的方法,不包括从超类中继承而来的方法
Method method = cls.getMethod(String name, Class<?>... parameterTypes)//返回指定的方法这里的name是方法名,parameterTypes表示参数列表
Method method = cls.getMethod("getName",String.class);
method.invoke(Object obj, Object... args);//这里的obj表示的调用该方法的对象,后面的args是参数列表;

关于invoke方法:第一个参数是隐式参数(this)第二个参数是显示参数,(java SE 5.0之前)必须传递一个数组对象,如果没有显示参数可以将传递一个null;如果是静态方法可以将第一参数忽略即将其设置为null;

  • <5>:访问域(属性)
Field field = cls.getFiled(String name);//返回声明在该类或其其超类中的指定的共有域
Field[] fields = cls.getFileds();//返回所有的声明在该类以及其超类中的共有域
Field field = cls.getDeclaredFiled(String name);//返回所有的声明在该类中的共有域;
Field[] fields = cls.getDeclaredFileds();//返回所有的声明在该类中的共有域;
Field field = cls.getDeclaredField("name");

ps一般情况下我们的私有属性是不可以进行访问,但java的反射也可以让我们访问到私有属性:

//通过调用下面方法表可将私有属性设置为可以访问的
Field.setAccessable(true)

补充例子1:使用Java的反射获取泛型信息:

class Person<T>{
    public Person(){
        //Type[] cls = ((ParameterizedType)(this.getClass().getGenericSuperclass())).getActualTypeArguments();
        //获取父类的子类传递过来的类型
        Type type= this.getClass().getGenericSuperclass();
        //转换成对应的参数类型
        ParameterizedType rtype =(ParameterizedType)type;
        Type[] types = rtype.getActualTypeArguments();
        for(Type t:types){
            System.out.println(((Class)t).getName());
        }
    }
}
class Student extends Person<String>{
    public Student(){
        System.out.println("我是子类的构造方法!");
    }
}
这里注意:调用子类构造器之前会先调用父类的构造器;

补充例子2:使用反射回去注解信息:
反射注解

  1. 要求
  • 注解的保留策略必须是RUNTIME(有三种状态:RESOURCE,CLASS,RUNTIME)
  1. 反射注解需要从作用目标上返回
  • 类上的注解,需要使用Class来获取
  • 方法上的注解,需要Method来获取
  • 构造器上的注解,需要Construcator来获取
  • 成员上的,需要使用Field来获取
    Class
    Method、Constructor、Field:这三个类都实现了:AccessibleObject类

它们都有一个方法:

  • Annotation getAnnotation(Class),返回目标上指定类型的注解!
  • Annotation[] getAnnotations(),返回目标上所有注解!

总结:以上就是自己关于java反射方面的简单的理解,如果内容有出错的地方望大家及时指正,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • 学习Android的同学注意了!!!学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Android学习交流群...
    kingZXY2009阅读 332评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 1.在C/C++中实现本地方法 生成C/C++头文件之后,你就需要写头文件对应的本地方法。注意:所有的本地方法的第...
    JayQiu阅读 2,354评论 0 3
  • 秋日的雨 滴嗒嗒 一盏一盏挂在车窗 车窗上映照出人的脸 呈现出五花八门的模样 雨刷的影子 左摇右摆 如同讨好这...
    水滴air阅读 288评论 0 2
  • 每次来北京,总会和你吃顿饭,聊聊天,走走路,然后各不相关很久。谢谢你这样无数次陪伴缩在壳里的我。
    aeolia阅读 149评论 0 1