第一:先认识Class类

类也是一种实例,类的实例创建有三种方式。

类的实例对象创建的方式有两种。以下的代码详细的介绍:

packagecom.company;import java.util.*;public classMain {public static voidmain(String[] args) {//类的实例创建有两种方式

Vae xs = newVae();

xs.music();//每个类都是一个实例的对象,Vae类是一个Class类的对象,其实例表达方式有3种//第1种,类的class

Class c1 = Vae.class;//第2种,类的实例的getClass

Class c2 =xs.getClass();//第3种,类的名字,这种是最常用的方式,我们在写Java反射的时候会经常使用

Class c3 = null;try{

c3= Class.forName("com.company.Vae");

}catch(ClassNotFoundException e) {

e.printStackTrace();

}

System.out.println(c1==c2);

System.out.println(c2==c3);//类的实例的第2种创建方式

try{

Vae xs2=(Vae) c1.newInstance();

xs2.music();

}catch(InstantiationException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

}

}classVae{public voidmusic(){

System.out.println("许嵩是最佳歌手");

}

}

这段代码的输出结果是:

下面来整理一下代码,首先,类的实例的创建的两种方法:

//第一种,最常见的new

Vae xs = newVae();//第二种,newInstance()方式,这种方式必须加try catch,否则会报错

try{

Vae xs2=(Vae) c1.newInstance();

xs2.music();

}catch(InstantiationException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

其次,类实例的创建方法,其实就是获取这个类的类型,有三种:

//第1种,类的class

Class c1 = Vae.class;//第2种,类的实例的getClass

Class c2 =xs.getClass();//第3种,类的名字,这种是最常用的方式,我们在写Java反射的时候会经常使用

Class c3 = null;try{

c3= Class.forName("com.company.Vae");

}catch(ClassNotFoundException e) {

e.printStackTrace();

}

第三种的确是最常见的,而且c1,c2,c3是一样的,输出==的时候结果是true。

这些就是Class类的全部知识。先记住。接下来讲解Java的动态加载和静态加载。很快,就可以触及到反射了。

第二:Java的静态加载和动态加载

加载分为静态加载和动态加载。

什么是静态加载呢?你写的代码在编译的时候,就是静态加载。凡是编译不能通过的代码,都是属于静态加载的。例如类创建对象的new关键字。

什么是动态加载呢?动态加载就是在代码运行的时候才加载的,C#里面有一个类型是dynamic,而在Java里面就是利用的我们上面讲的Class.forName

我先来举个例子,解释一下上面两句话:

importjava.util.Scanner;public classMain {public static voidmain(String[] args) {

Scanner scan=newScanner(System.in);

Start(scan.nextLine());

}public static voidStart(String name)

{if("Vae".equals(name)){

Vae xs=newVae();

xs.music();

}else{

System.out.println("我是出口");

}

}

这是我在idea里面写的代码,编译的时候,报错,说没有Vae这个类。这就说明了在new Vae的对象的时候,编译是不通过的,因为在编译的时候就已经开始加载了。这说明了,new 类的对象是属于静态加载的。

现在我们写一个Vae类出来:

public classVae {public voidmusic() {

System.out.println("许嵩是最佳歌手");

}

}

然后我们把Vae类名传递过去。运行,输入 Vae

结果如下:

非常完美。那么现在问题来了。很严重的问题。我现在不想用Vae类了,使用Vae类只能输出许嵩是最佳歌手。这个是许嵩的专属类。

我还想去输入其它歌手怎么办?例如我想添加一个shuyunquan类,去输出蜀云泉是一名歌手。那么我们要做两件事:

1.新写一个shuyunquan类

2.在Main类的Start方法中,必须新加一个if语句去判断我的输入是否等于shuyunquan

第一步是毫无疑问必须要写的,但是第二步!!!假如我们已经发布了代码,你怎么改?假如我想再增加10名歌手,你怎么改?

一个一个的在Start方法里面加?

这是一个很愚蠢的行为。这个时候我们需要使用我们第一步中学到的Class类的知识。

我改动了Main类中的Start方法,如下:

importjava.util.Scanner;public classMain {public static voidmain(String[] args) {

Scanner scan=newScanner(System.in);

Start(scan.nextLine());

}public static voidStart(String name)

{try{

Class c=Class.forName(name);

singer s=(singer)c.newInstance();

s.music();

}catch(ClassNotFoundException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}catch(InstantiationException e) {

e.printStackTrace();

}

}

}

可以看到,我使用Class.forName方法获取了我输入的类类型。然后使用newInstance方法new出了一个类的实例对象。但是newInstance方法是必须要加强制类型转换的怎么办?

因为我输入的都是歌手类。所以我写了一个接口,定义为singer:

interfacesinger {public voidmusic();

}

然后给我的Vae类实现这个接口:

public class Vae implementssinger {public voidmusic() {

System.out.println("许嵩是最佳歌手");

}

}

现在,如果我想再加10个,20个歌手进来,都是完全没有问题的。我只需要写出我需要的歌手类。然后继承这个接口。再然后,我直接输入就可以了。

完全不需要修改我的Main类中的Start方法。这一点和QQ的在线更新啊,其它软件的升级功能啊,貌似都是这样实现的。

第三:Java获取类的方法名,方法返回值类型,方法的参数类型

在第一我们学到了Java如何去获取类类型,在第二我们使用了类类型去完成了Java的动态加载。这一次,我们学习下,Java如何去获取方法的详细信息。

importjava.lang.reflect.Method;public classMain {public static voidmain(String[] args) {

Vae xs=newVae();//getMethods()是获取所有的public方法,包括父类继承的,系统写的。getDeclaredMethods()是获取所有自己写的方法,public和private都获取。我喜欢getDeclaredMethods()//Method [] methods=xs.getClass().getMethods();

Method [] methods=xs.getClass().getDeclaredMethods();for(Method temp:methods) {//获取方法的返回值类型

Class returnType=temp.getReturnType();

System.out.print("方法名"+temp.getName()+" 返回值类型"+returnType);///获取方法名//System.out.println(temp.getName());

///获取参数数组

Class [] params=temp.getParameterTypes();for(Class param:params) {

System.out.print(" 方法的参数"+param.getSimpleName()+",");

}

System.out.println();

}

}

}

第一亮点:import java.lang.reflect.Method  我们已经引用了Java反射

第二亮点:getMethods()和getDeclaredMethods()这两个方法的区别。

getMethods()是获取所有的public方法,包括父类继承的,系统写的。getDeclaredMethods()是获取所有自己写的方法,public和private都获取。

我特意传进去的我写的Vae类,我们来看看我的Vae类:

public class Vae implementssinger {public voidmusic() {

System.out.println("许嵩是最佳歌手");

}public int test(inta,String b) {return 1;

}

}

里面有两个方法,参数,返回值一目了然。我们执行上面的代码,结果如下:

完美!自己手动写写吧。

第四:Java获取类的成员变量的名称,类型 。获取构造函数的名称,参数类型。

由于第四和第三步是差不多的。所以我直接贴出代码和结果了

//获取成员变量

Field [] fs=xs.getClass().getFields(); //只能获取public

Field [] fs1=xs.getClass().getDeclaredFields(); //获取所有

for(Field field:fs1) {//成员变量的类型

Class fieldType=field.getType();

String typeName=fieldType.getName();//成员变量的名称

String fileName=field.getName();

System.out.println("变量名:"+fileName+" 变量类型"+typeName);

}//获取构造函数信息

Constructor [] cs=xs.getClass().getConstructors(); //获取public的构造函数

Constructor [] cs1=xs.getClass().getDeclaredConstructors(); //获取所有的构造函数,包括public和private

for(Constructor constructor:cs) {

System.out.print("构造函数名称是:" + constructor.getName() + " 构造函数的参数有:");

Class[] paramTypes=constructor.getParameterTypes();for(Class class1:paramTypes){

System.out.print(class1.getName()+",");

}

System.out.println();

}

就这么多,还是以我的Vae类为例子

public class Vae implementssinger {public int age=32;public String name="许嵩";private String love="写歌";public voidmusic() {

System.out.println("许嵩是最佳歌手");

}public int test(inta,String b) {return 1;

}

}

结果:

自己敲一敲代码,记一记就完事了。下面开始讲反射。

第五:方法的反射

终于,我们开始方法的反射了。先看代码:

packagecom.company;importjava.lang.reflect.Method;public classMain {public static voidmain(String[] args) {

Class c=Vae.class;

Vae xs=newVae();//方法的反射

try{

Method s=c.getMethod("music", int.class, int.class);//invoke方法就是反射的方法,Object是接收的返回值,如果是void方法,返回值是null

Object object=s.invoke(xs,2,3);

System.out.println(object);//有返回值的方法

Method s1=c.getMethod("music", String.class, String.class);

object=s1.invoke(xs,"许嵩","蜀云泉");

System.out.println(object);//没有参数的方法

Method s2=c.getMethod("music");

object=s2.invoke(xs);

System.out.println(object);

}catch(Exception e) {

e.printStackTrace();

}

}

}classVae{public void music(int a,intb){

System.out.println(a+b);

}publicString music(String a,String b){return a+b;

}public void music(){ System.out.println("没有参数的空方法");}

}

看看输出的结果:

现在来讲解一下方法的反射。Invoke方法是重点,现在写到这里应该是有两个疑问的?

第一:我既然实例化了Vae类的对象,我为什么不直接xs.music(),反而要反射的去做。这不是麻烦吗?

存疑,这个我暂时没想通。

第二:在反射方法的时候,我怎么知道参数怎么填写?有几个?什么类型的?

这个疑问在想出来的时候就已经想到答案了,答案就是第四步,我们可以输出方法的名称和参数类型,个数还有方法的返回值类型。其实。。。这也完全没有必要,因为你的那些类都是继承了接口的,你只需要看看接口有哪些方法,就可以了。所以这个问题完全不是问题。

其它的在代码的注释里面,已经写的很清楚了。

还有一个反射去绕过泛型的例子待补充。我在网上搜了一下,貌似都说反射这个技能比较消耗资源,在普通情况下,是不建议使用的。反射大量应用的场景应该是写框架的时候。

我再找找看看有没有反射的最佳实践吧。反正我学习到这里,只觉得第二步是有意思的。

java反射为什么消耗资源_Java反射笔记相关推荐

  1. java 反射 慢在那里_Java 反射到底慢在哪?

    反射具体是怎么影响性能的?这引起了我的反思. 是啊,在阐述某个观点时确实有必要说明原因,并且证明这个观点是对的,虽然反射影响性能人尽皆知,我曾经也真的研究过反射是否存在性能问题,但并没有在写文章的时候 ...

  2. java反射用在哪里_Java反射

    昨天去参加比赛了,所以没有进行博客迁移.人生中的第一场健体比赛,虽然没得奖,但是收获和带来的思考颇丰.意外地进入了男子B组(174以上)的半决赛,然后在半决赛的时候还被裁判员点名出去单独比较,这个很让 ...

  3. java获取object属性值_java反射获取一个object属性值代码解析

    有些时候你明明知道这个object里面是什么,但是因为种种原因,你不能将它转化成一个对象,只是想单纯地提取出这个object里的一些东西,这个时候就需要用反射了. 假如你这个类是这样的: privat ...

  4. java反射机制详解_Java反射机制详解

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...

  5. java反射设置属性值_Java反射如何有效的修改final属性值详解

    前言 以前写过一篇 Java 反射修改 final 属性值,本文将在这里重新温习一下Java反射如何有效的修改final属性值,下面话不多说了,来一起看看详细的介绍: 假设有个类 class Pers ...

  6. java反射的编译过程_Java反射机制小结和实际操作

    一.什么是反射 1.编译和运行 在了解什么是Java反射机制前,先聊聊Java的编译和运行. 还记得第一次使用记事本编写第一个Java程序的场景吗?通过命令窗口,使用javac命令编译一个.java文 ...

  7. java 获取接口的注解_java反射注解妙用-获取所有接口说明

    前言 最近在做项目权限,使用shiro实现restful接口权限管理,对整个项目都进行了重构.而权限管理需要用到所有的接口配置,包括接口url地址,接口唯一编码等.想要收集所有的接口信息,如果工程接口 ...

  8. java反射有什么用_java反射的作用知识点总结

    Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在.灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助. 什么是Java的反射? 反射是Java的特征之一,是一种间接操作 ...

  9. java反射机制详解_JAVA反射机制详解_JSP/Java编程_互联网开发技术网_传播最新的编程技术_php361.com...

    今天,下午在和朋友聊天的时候,聊起了反射这个话题. 我们就从下面这个段简单的代码开始吧. 这个代码输出什么,想必大部分的读者跟我一样,会很快地知道答案:0 1 2 3 4 5 6 7 8 9.事实也是 ...

最新文章

  1. 安卓真机测试安装时报错
  2. 由于Coinbase插件,BCH被5000万商家接受
  3. java打开db文件_java 读取DB.properties文件方式 | 学步园
  4. zabbix监控TCP连接状态
  5. 自动驾驶中的深度学习
  6. 前端小知识-html5
  7. 微型计算机中硬盘工作时 应注意避免,1硬盘工作时应特别注意避免(B)
  8. jtopo更改节点选中框的颜色
  9. cmd命令跳舞代码_Golang语言元编程之代码生成
  10. ERROR: Cannot uninstall ‘PyYAML‘. It is a distutils installed project and thus we cannot...
  11. ZJM与生日礼物【字典树】
  12. 3GPP TS 23501-g51 中英文对照 | 4.3.3 Interworking between 5GC via non-3GPP access and E-UTRAN connected t
  13. 外卖平台乱象迭出!究竟谁该负责?
  14. 五、Hystrix断路器
  15. 功率单位mw和dbm换算
  16. 暨南大学计算机研究生进腾讯,腾讯内容开放平台
  17. Java —— 初识集合
  18. Springboot 一文搞懂AOP面向切面编程
  19. Java多线程面试题之如何让主线程等子线程执行完之后再执行
  20. 如何计算两个日期之间相隔的天数?calendar的用法

热门文章

  1. 为什么 MongoDB 使用 B 树?
  2. 目标检测tricks(基于detectron2)
  3. Android 性能优化之——高性能使用图片全面总结
  4. 这种公司再也呆不下去了!我要跳槽!
  5. 分三种情况C语言编程,浅谈C语言教学的现状及几点建议.doc
  6. python练习题:程序员问卷调查
  7. ST推出 28nm MCU ,NXP更狠,推出16nm MCU
  8. linux swap空间不足,swap空间不足问题解决
  9. linux调节伽马值软件,LightBulb(屏幕伽马值自动调整)
  10. Matlab下地形图绘图包m_map绘制晕渲(shaded relief)地形图