1. 介绍

反射是一种能够在程序运行时动态访问、修改某个类中任意属性和方法的机制。

具体:

对于任意一个类,都能够知道这个类的所有属性和方法

对于任意一个对象,都能够调用它的任意一个方法和属性

在运行时,当加载完类之后,JVM在堆内存中会自动产生一个Class类型的对象,这个对象包含了完整的类的结构信息

这个Class对象就像一面镜子,透过这个镜子看到类的结构

那么,如何得到这个Class对象呢?以下可否

Class c = new Class();

答案是不行的,因为Class的构造函数定义为私有的,只有JVM可以访问

privateClass(ClassLoader loader) {

classLoader=loader;

}

Class对象获取的三种方式

Class c1 = Code.class;

Class c2=code1.getClass();

Class c3= Class.forName("com.trigl.reflect.Code");

举例

public classTestStudent {public static void main(String[] args) throwsClassNotFoundException {

Student student= new Student(1, "Jack");

Class class1=student.getClass();

Class class2= Student.class;

Class class3= Class.forName("com.example.refs.Student");

System.out.println(class1);

System.out.println(class2);

System.out.println(class3);

}

}

输出

classcom.example.refs.Studentclasscom.example.refs.Studentclass com.example.refs.Student

2. Java反射相关操作

本文以Student类为例:

接口

packagecom.example.refs;public interfaceInterFace {voidread();

}

packagecom.example.refs;public class Student implementsInterFace{private intid;publicString name;publicStudent() {}public Student(intid, String name) {this.id =id;this.name =name;

}public void setId(intid) {this.id =id;

}private intgetId() {returnid;

}

@Overridepublic voidread() {}

}

以下具体介绍下具体的用法

2.1 类名称、包名

public classClassName {public static voidmain(String[] args) {

Class> class2 = Student.class;

System.out.println("getSimpleName:" +class2.getSimpleName());

System.out.println("getName:" +class2.getName());

System.out.println("getPackage:" +class2.getPackage());

}

}

输出

getSimpleName:Student

getName:com.example.refs.Student

getPackage:package: com.example.refs

2.2 方法

public Method getDeclaredMethod(String name, Class>...parameterTypes) // 得到本类所有的方法(public/private/proteceted...)public Method getMethod(String name, Class>...parameterTypes) //得到该类所有的public方法,包括父类

举例

public classMethodTest {public static voidmain(String[] args) {

Class> class1 = Student.class;

Method[] methods=class1.getMethods();

Method[] declaredMethods=class1.getDeclaredMethods();for(Method method : methods) {

System.out.println("getMethods: " +method);

}

System.out.println();for(Method method : declaredMethods) {

System.out.println("getDeclaredMethods: " +method);

}

}

}

结果

getMethods: public void com.example.refs.Student.read()

getMethods: public void com.example.refs.Student.setId(int)

getMethods: public final void java.lang.Object.wait() throws java.lang.InterruptedException

getMethods: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

getMethods: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

getMethods: public boolean java.lang.Object.equals(java.lang.Object)

getMethods: public java.lang.String java.lang.Object.toString()

getMethods: public native int java.lang.Object.hashCode()

getMethods: public final native java.lang.Class java.lang.Object.getClass()

getMethods: public final native void java.lang.Object.notify()

getMethods: public final native void java.lang.Object.notifyAll()

getDeclaredMethods: public void com.example.refs.Student.read()

getDeclaredMethods: private int com.example.refs.Student.getId()

getDeclaredMethods: public void com.example.refs.Student.setId(int)

指定方法

public classMethodChangeVal {public static void main(String[] args) throwsIllegalAccessException, InstantiationException,

NoSuchMethodException, InvocationTargetException {

Class clazz= Student.class;

Object obj=clazz.newInstance();

Method methodGet= clazz.getDeclaredMethod("getId");

Method methodSet= clazz.getDeclaredMethod("setId", int.class);

methodSet.invoke(obj,123);

System.out.println(methodGet.invoke(obj));

}

}

异常

Exception in thread "main" java.lang.IllegalAccessException: Class

com.example.refs.MethodChangeVal can not access a member of class

com.example.refs.Student with modifiers "private"

原因:setId为私有方法,利用反射时会进行安全检查,用setAccessible(true)不进行安全检查,可以直接对调用私有方法、修改私有变量

public classMethodChangeVal {public static void main(String[] args) throwsIllegalAccessException, InstantiationException,

NoSuchMethodException, InvocationTargetException {

Class clazz= Student.class;

Object obj=clazz.newInstance();

Method methodGet= clazz.getDeclaredMethod("getId");

Method methodSet= clazz.getDeclaredMethod("setId", int.class);

methodGet.setAccessible(true);

methodSet.invoke(obj,123);

System.out.println(methodGet.invoke(obj));

}

}

2.3 构造函数

public Constructor getDeclaredConstructor(Class>... parameterTypes)public Constructor getConstructor(Class>... parameterTypes)

Constructor>[] allConstructors = class1.getDeclaredConstructors();//获取class对象的所有声明构造函数

Constructor>[] publicConstructors = class1.getConstructors();//获取class对象public构造函数

Constructor> constructor = class1.getDeclaredConstructor(String.class);//获取指定声明构造函数

Constructor publicConstructor = class1.getConstructor(String.class);//获取指定声明的public构造函数

举例

public classConstuctorTest {public static voidmain(String[] args) {

Class class2= Student.class;

Constructor>[] constructors =class2.getConstructors();for (Constructor>constructor : constructors) {

System.out.println(constructor+ ", Name:" +constructor.getName());

}

}

}

结果

publiccom.example.refs.Student(), Name:com.example.refs.Studentpublic com.example.refs.Student(int,java.lang.String), Name:com.example.refs.Student

2.4 成员变量

getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。

getFields()获得某个类的所有的公共(public)的字段,包括父类。

举例

public classFieldTest {public static voidmain(String[] args) {

Class> aClass = Student.class;

Field[] declardFields=aClass.getDeclaredFields();

Field[] fields=aClass.getFields();for(Field field : declardFields) {

System.out.println("declaredField: " +field);

}

System.out.println();for(Field field : fields) {

System.out.println("field: " +field);

}

}

}

结果

declaredField: private intcom.example.refs.Student.id

declaredField:publicjava.lang.String com.example.refs.Student.name

field:public java.lang.String com.example.refs.Student.name

2.5 修饰符

举例

public classModifierTest {public static voidmain(String args[]) {

Class aClass= Student.class;int modifier =aClass.getModifiers();

System.out.println("modifier:" +modifier);

System.out.println(String.format("isAbstract: %s", Modifier.isAbstract(modifier)));

System.out.println(String.format("isPublic: %s", Modifier.isPublic(modifier)));

System.out.println(String.format("isStatic: %s", Modifier.isStatic(modifier)));

System.out.println(String.format("isFinal: %s", Modifier.isFinal(modifier)));

System.out.println(String.format("isSynchronized: %s", Modifier.isSynchronized(modifier)));

}

}

结果

modifier:1isAbstract:falseisPublic:trueisStatic:falseisFinal:falseisSynchronized:false

2.6 父类

public classGetParent {public static voidmain(String[] args) {

Class class2= Student.class;

System.out.println(class2.getSuperclass());

}

}

结果

class java.lang.Object

2.7 接口

public classInterfaceTest {public static voidmain(String[] args) {

Class> clazz = Student.class;

Class>[] inters =clazz.getInterfaces();for(Class>classIn : inters) {

System.out.println(classIn);

}

}

}

输出

interface com.example.refs.InterFace

2.8 创建对象实例

举例用2种方法创建

public classNewInstanceTest {public static void main(String[] args) throwsIllegalAccessException, InstantiationException,

NoSuchMethodException, InvocationTargetException {

Class clazz= Student.class;

Object obj=clazz.newInstance();

Constructor> constructor =clazz.getDeclaredConstructor();

Object obj2=constructor.newInstance();

Constructor> constructor2 = clazz.getDeclaredConstructor(int.class, String.class);

Object obj3= constructor2.newInstance(1, "HanMeimei");

System.out.println(obj);

System.out.println(obj2);

System.out.println(obj3);

}

}

结果

2.9 注解

自定义一个注解

@Retention(RetentionPolicy.RUNTIME)

@interfaceMyAnnotation {publicString name();public String value();

注:RetentionPolicy.RUNTIME 这个表示运行期注解,这样在反射的时候才能取到

举例

public classAnnotationTest {

@MyAnnotation(name="someName", value = "Hello World")public voiddoSomething() {

}

@Deprecatedpublic voiddelFunc() {

System.out.println("Hello");

}public static void main(String[] args) throwsNoSuchMethodException {

Class clazz= AnnotationTest.class;

Method method= clazz.getMethod("doSomething");

Annotation[] declaredAnnotations=method.getDeclaredAnnotations();for(Annotation annotation : declaredAnnotations) {if (annotation instanceofMyAnnotation) {

MyAnnotation myAnnotation=(MyAnnotation)annotation;

System.out.println("name:" +myAnnotation.name());

System.out.println("value:" +myAnnotation.value());

}else{

System.out.println(annotation);

}

}

}

}

结果

name:someName

value:Hello World

2.10 泛型

参数类型、返回值类型举例

public classGenericTest {public void test01(Map map, Listlist) {

System.out.println("test01");

}public Maptest02() {

System.out.println("test02");return null;

}public static void main(String[] args) throwsNoSuchMethodException {

Method method= GenericTest.class.getMethod("test01", Map.class, List.class);

Type[] types=method.getGenericParameterTypes();for(Type type : types) {

System.out.println("#:" +type);if (type instanceofParameterizedType) {

Type[] genericType=((ParameterizedType)type).getActualTypeArguments();for(Type ontGenericType : genericType) {

System.out.println("泛型类型:" +ontGenericType);

}

}

}

Method method2= GenericTest.class.getMethod("test02");

Type returnType=method2.getGenericReturnType();

System.out.println("\nReturntype" +returnType);if (returnType instanceofParameterizedType) {

Type[] genericTypes=((ParameterizedType)returnType).getActualTypeArguments();for(Type type : genericTypes) {

System.out.println("返回值,泛型类型:" +type);

}

}

}

}

结果

#:java.util.Map

泛型类型:class java.lang.String

泛型类型:class com.example.refs.Student

#:java.util.List

泛型类型:class com.example.refs.Student

Returntypejava.util.Map

返回值,泛型类型:class java.lang.Integer

返回值,泛型类型:class com.example.refs.Student

2.11 数组

public classArrayTest {public static voidmain(String[] args) {int[] intArray = (int[])Array.newInstance(int.class, 3);

Array.set(intArray,0, 123);

Array.set(intArray,1, 124);

Array.set(intArray,2, 125);for (int i = 0; i < Array.getLength(intArray); ++i) {

System.out.println(String.format("array[%s]:%s", i, Array.get(intArray, i)));

}

Class aClass=intArray.getClass();

System.out.println("intArray是否是数组类型:" +aClass.isArray());

System.out.println("intArray成员类型:" +aClass.getComponentType());

}

}

结果

array[0]:123

array[1]:124

array[2]:125

intArray是否是数组类型:true

intArray成员类型:int

3. 分析

3.1 使用场景

操作因访问权限限制的属性和方法

实现自定义注解

动态加载第三方jar包

按需加载类,节省编译和初始化APK的时间

3.2 优缺点

优点:灵活、自由度高:不受类的访问权限限制

缺点

性能问题:通过反射访问、修改类的属性和方法时会远慢于直接操作,但性能问题的严重程度取决于在程序中是如何使用反射的。如果使用得很少,不是很频繁,性能将不是问题

安全性问题:反射可以随意访问和修改类的所有状态和行为,破坏了类的封装性,如果不熟悉被反射类的实现原理,随意修改可能导致潜在的逻辑问题

兼容性问题:因为反射会涉及到直接访问类的方法名和实例名,不同版本的API如果有变动,反射时找不到对应的属性和方法时会报异常

3.3 说明

通过反射访问方法比实例慢很多

有用到反射的类不能被混淆

反射存在性能问题,但使用不频繁、按需使用时,对程序性能影响并不大

反射存在安全性问题,因为可以随意修改类的所有状态和行为(包括private方法和实例)

使用反射访问Android的API时需要注意因为不同API版本导致的兼容性问题

3.4 性能对比

不使用反射、启用安全检查、启用安全检查进行对比

public classTestReflect {

@Testpublic voidtestNoneReflect() {

Student oneStudent= new Student(1, "HanMeimei");long start =System.currentTimeMillis();for (long i = 0; i < Integer.MAX_VALUE; ++i) { oneStudent.setId(1); }long count = System.currentTimeMillis() -start;

System.out.println("没有反射, 共消耗 毫秒");

}

@Testpublic void testNotAccess() throwsClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException,

InvocationTargetException {

Student oneStudent= new Student(1, "HanMeimei");

Method method= Class.forName("com.example.refs.Student").getMethod("setId", int.class);long start =System.currentTimeMillis();for (long i = 0; i < Integer.MAX_VALUE; ++i) { method.invoke(oneStudent, 1); }long count = System.currentTimeMillis() -start;

System.out.println("启用安全检查, 共消耗 毫秒");

}

@Testpublic void testUseAccess() throwsClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

Student oneStudent= new Student(1, "HanMeimei");

Method method= Class.forName("com.example.refs.Student").getMethod("setId", int.class);

method.setAccessible(true);long start =System.currentTimeMillis();for (long i = 0; i < Integer.MAX_VALUE; ++i) { method.invoke(oneStudent, 1); }long count = System.currentTimeMillis() -start;

System.out.println("取消安全检查, 共消耗 毫秒");

}

}

结果对比

差异

耗时(ms)

没用反射

952

取消安全检查

4283

启用安全检查

14892

原文:http://www.cnblogs.com/kaituorensheng/p/7398069.html

java反射 interface_Java反射相关推荐

  1. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  2. Java中为什么需要反射?反射要解决什么问题?

    Java中为什么需要反射?反射要解决什么问题? 参考文章: (1)Java中为什么需要反射?反射要解决什么问题? (2)https://www.cnblogs.com/buoge/p/9285142. ...

  3. JAVA基础--JAVA中的反射机制详解

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

  4. java 反射 ppt_Java反射的基本使用

    这里是修真院后端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析后端知识/技能,本篇分享的是: [Java反射的 ...

  5. Java 学习笔记 反射与迭代器

    反射 使用反射获得Class类 Class cls = Class.forName("全类名") //包括包名 Class cls = xx.Class;//xx代表类名 Clas ...

  6. Java反射机制的基本概念与使用_Java进阶之reflection(反射机制)——反射概念与基础...

    反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...

  7. java f反射_java反射机制

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

  8. java 有哪些反射机制_Java 的反射机制你了解多少?

    不知道多少次听说过了Java反射机制的使用,比如:Spring 框架如何实例化IoC容器中的Bean,编码过程中如何动态的清理对象中的字段信息等等.工作中只是听说.看同事们编码实践,但是自己却只是概念 ...

  9. Java 中使用反射来创建对象、调用方法

    Java 中使用反射来创建对象.调用方法 反射创建对象 反射调用方法 反射调用私有方法 反射调用可变参私有方法 反射调用的方法自身可以抛出异常的情形   假设已有下面的类: import java.l ...

最新文章

  1. 使用jQuery for Asp.Net 我的开发环境配置
  2. 解决AttributeError: module ‘cv2.cv2‘ has no attribute ‘estimateRigidTransform‘
  3. 数据中心调试的重新思考
  4. 汉仪尚巍手书可以商用吗_【商用车维修】夏天修空调可以撑起全年修车收入的一半,你会了吗?...
  5. ffmpeg.exe 笔记
  6. 启明星辰集团DT总部落地杭州 数据绿洲版图驱动未来发展
  7. 详解javascript的bind方法
  8. linux centos7.9图形界面版本下载_适合在任何地方使用的 Linux:15 个小型 Linux 发行版...
  9. 数值分析与算法——读书笔记(一)
  10. 增粉的各种方法【微信 / 微博 增加粉丝的108种方法】
  11. Notepad++的字体设置加Consolas和微软雅黑混合字体
  12. JavaScript知识点全面概括与总结(上)
  13. smart 支持标签
  14. 桌面最前 desk_使用T3Desk在3D桌面环境中管理应用程序
  15. vue 打包之后不兼容ie_vue项目打包后在IE浏览器报错,页面显示空白
  16. 【STM32F4系列】【HAL库】旋转编码器(EC11)
  17. 从思维转变看数字化转型 IT 经营
  18. GBase UP是做什么的
  19. PS2019计算机丢失,小编教您ps2019中如何调出历史记录
  20. Cisco之show ip arp 与 show mac-address-table

热门文章

  1. 清华大学环境工程专业考研经验分享
  2. 大数据笔试题目练习(附答案)
  3. surface pro java_微软新发布的Surface Pro与Surface Pro4有什么区别?值得你升级吗?
  4. unique去重函数
  5. 女生被逼疯的日记(课余篇)
  6. leetcode-4.11[1276. 不浪费原料的汉堡制作方案、237. 删除链表中的节点、657. 机器人能否返回原点](python解法)
  7. 论流氓软件,以及其解决方法。
  8. 学英语《每日一歌》之take me to your heart
  9. 码绘让你眼前一新——雪梨的码绘点评Time
  10. 表格练习(工商银行电子汇款单)表单练习(用户注册)