08.Java反射问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了08.Java反射问题相关的知识,希望对你有一定的参考价值。
目录介绍
- 8.0.0.1 反射的原理是什么?有哪些途径获取到Class对象,Class类的含义和作用是什么?什么是class类?
- 8.0.0.2 有哪些方式可以提高反射效率?为何反射消耗性能?究竟是怎么影响的,举例说明?
- 8.0.0.3 java反射机制提供了什么功能?发射具有暴力访问权限,如何防止反射序列化***单例?
- 8.0.0.4 通过反射获得泛型的实际类型参数?反射获取构造方法,变量,方法的方法是哪些?
- 8.0.0.5 getGenericParameterTypes 与 getParameterTypes区别?
- 8.0.0.6 反射有什么作用和应用?反射和注解相比,为何反射消耗性能,有什么优缺点?
好消息
- 博客笔记大汇总【15年10月到至今】,包括Java基础及深入知识点,android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计500篇[近100万字],将会陆续发表到网上,转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有博客将陆续开源到GitHub!
8.0.0.1 反射的原理是什么?有哪些途径获取到Class对象,Class类的含义和作用是什么?什么是class类?
- 反射的原理是什么?
- 反射是为了能够动态的加载一个类,动态的调用一个方法,动态的访问一个属性等动态要求而设计的。它的出发点就在于JVM会为每个类创建一个java.lang.Class类的实例,通过该对象可以获取这个类的信息,然后通过使用java.lang.reflect包下得API以达到各种动态需求。
- 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 有哪些途径获取到Class对象,Class类的含义和作用是什么?
- 每一个Class类的对象就代表了一种被加载进入JVM的类,它代表了该类的一种信息映射。开发者可以通过3种途径获取到Class对象。
- 技术博客大总结
- 第一种方式:Class的forName()方法的返回值就是Class类型,也就是动态导入类的Class对象的引用。
- public static Class<?> forName(String className) throws ClassNotFoundException
- 第二种方式:每个类都会有一个名称为Class的静态属性,通过它也是可以获取到Class对象的,示例代码如下:
Class<Student> clazz = Student.class; // 访问Student类的class属性
- 第三种方式:Object类中有一个名为getClass的成员方法,它返回的是对象的运行时类的Class对象。因为Object类是所有类的父类,所以,所有的对象都可以使用该方法得到它运行时类的Class对象,示例代码如下:
Student stu = new Student(); Class<Student> clazz = stu.getClass(); // 调用Student对象的getName方法
- 什么是class类?
- .class文件:是由一个.java文件通过编译过程生成的.class文件。Class对象:当Java虚拟机加载一个.class文件到内存时,都会生成一个对应的Class对象,注意的是这个Class对象有且只有一个存在于内存当中。
8.0.0.2 有哪些方式可以提高反射效率?为何反射消耗性能?究竟是怎么影响的,举例说明?
-
有哪些方式可以提高反射效率?
- 善用API:比如,尽量不要getMethods()后再遍历筛选,而直接用getMethod(methodName)来根据方法名获取方法。
- 技术博客大总结
- 适当使用缓存:比如,需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多:
// 1. 没有缓存 void createInstance(String className){ return Class.forName(className).newInstance(); }
// 2. 缓存forName的结果
void createInstance(String className){
cachedClass = cache.get(className);
if (cachedClass == null){
cachedClass = Class.forName(className);
cache.set(className, cachedClass);
}
return cachedClass.newInstance();
} - 为何反射消耗性能?
8.0.0.3 java反射机制提供了什么功能?发射具有暴力访问权限,如何避免反射***?
- java反射机制提供了什么功能?
- 在运行时能够判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任一对象的方法技术博客大总结
- 在运行时创建新类对象
- 发射具有暴力访问权限,如何避免反射***?
-
如何防止反射序列化***单例
- 枚举单例
public enum Singleton { INSTANCE { @Override protected void read() { System.out.println("read"); } @Override protected void write() { System.out.println("write"); } }; protected abstract void read(); protected abstract void write(); }
-
class文件:
public abstract class Singleton extends Enum{ private Singleton(String s, int i){ super(s, i); } protected abstract void read(); protected abstract void write(); public static Singleton[] values(){ Singleton asingleton[]; int i; Singleton asingleton1[]; System.arraycopy(asingleton = ENUM$VALUES, 0, asingleton1 = new Singleton[i = asingleton.length], 0, i); return asingleton1; } public static Singleton valueOf(String s) { return (Singleton)Enum.valueOf(singleton/Singleton, s); } Singleton(String s, int i, Singleton singleton){ this(s, i); } public static final Singleton INSTANCE; private static final Singleton ENUM$VALUES[]; static { INSTANCE = new Singleton("INSTANCE", 0){ protected void read(){ System.out.println("read"); } protected void write(){ System.out.println("write"); } }; ENUM$VALUES = (new Singleton[] { INSTANCE }); } }
- 类的修饰abstract,所以没法实例化,反射也无能为力。关于线程安全的保证,其实是通过类加载机制来保证的,我们看看INSTANCE的实例化时机,是在static块中,JVM加载类的过程显然是线程安全的。对于防止反序列化生成新实例的问题还不是很明白,一般的方法我们会在该类中添加上如下方法,不过枚举中也没有显示的写明该方法。技术博客大总结
//readResolve to prevent another instance of Singleton private Object readResolve(){ return INSTANCE; }
- 类的修饰abstract,所以没法实例化,反射也无能为力。关于线程安全的保证,其实是通过类加载机制来保证的,我们看看INSTANCE的实例化时机,是在static块中,JVM加载类的过程显然是线程安全的。对于防止反序列化生成新实例的问题还不是很明白,一般的方法我们会在该类中添加上如下方法,不过枚举中也没有显示的写明该方法。技术博客大总结
- 枚举单例
8.0.0.4 通过反射获得泛型的实际类型参数?反射获取构造方法,变量,方法的方法是哪些?
-
通过反射获得泛型的实际类型参数
- 把泛型变量当成方法的参数,利用Method类的getGenericParameterTypes方法来获取泛型的实际类型参数
-
例子:
public class GenericTest { public static void main(String[] args) throws Exception { getParamType(); } /*利用反射获取方法参数的实际参数类型*/ public static void getParamType() throws NoSuchMethodException{ Method method = GenericTest.class.getMethod("applyMap",Map.class); //获取方法的泛型参数的类型 Type[] types = method.getGenericParameterTypes(); System.out.println(types[0]); //参数化的类型 ParameterizedType pType = (ParameterizedType)types[0]; //原始类型 System.out.println(pType.getRawType()); //实际类型参数 System.out.println(pType.getActualTypeArguments()[0]); System.out.println(pType.getActualTypeArguments()[1]); } /*供测试参数类型的方法*/ public static void applyMap(Map<Integer,String> map){ } }
- 输出结果:
java.util.Map<java.lang.Integer, java.lang.String> interface java.util.Map class java.lang.Integer class java.lang.String
- 反射获取构造方法,变量,方法的方法是哪些?技术博客大总结
- 在反射包中,我们常用的类主要有Constructor类表示的是Class 对象所表示的类的构造方法,利用它可以在运行时动态创建对象、Field表示Class对象所表示的类的成员变量,通过它可以在运行时动态修改成员变量的属性值(包含private)、Method表示Class对象所表示的类的成员方法,通过它可以动态调用对象的方法(包含private)。
8.0.0.5 getGenericParameterTypes 与 getParameterTypes区别?
- getGenericParameterTypes 与 getParameterTypes区别?
- getGenericParameterTypes 与 getParameterTypes 都是获取构成函数的参数类型
- 前者返回的是Type类型,后者返回的是Class类型,由于Type顶级接口,Class也实现了该接口,因此Class类是Type的子类,Type 表示的全部类型而每个Class对象表示一个具体类型的实例,如String.class仅代表String类型。由此看来Type与 Class 表示类型几乎是相同的,只不过Type表示的范围比Class要广得多而已。当然Type还有其他子类,如:
- TypeVariable:表示类型参数,可以有上界,比如:T extends Number
- ParameterizedType:表示参数化的类型,有原始类型和具体的类型参数,比如:List<String>
- WildcardType:表示通配符类型,比如:?, ? extends Number, ? super Integer
8.0.0.6 反射有什么作用和应用?反射和注解相比,为何反射消耗性能,有什么优缺点?
- 反射有什么作用和应用?
- 含义:在运行状态中,对于任意一个类都能知道它的所有属性和方法,对于任何一个对象都能够调用它的任何一个方法和属性。
- 功能:动态性,体现在:在运行时判断任意一个类所具有的属性和方法; 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时调用任意一个对象的方法;生成动态代理
- 为何反射消耗性能
- 有什么优缺点
- 优点
- 动态编译:运行时确定类型,绑定对象。动态编译最大限度的发挥了java的灵活性,体现了多态的应用,有利于降低类之间的耦合性。
- 反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在开发中。它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
- 优点
其他介绍
01.关于博客汇总链接
02.关于我的博客
- 我的个人站点:www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:[email protected]
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
以上是关于08.Java反射问题的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?