---恢复内容开始---
- 主要是指程序可以访问、检测和修改它本身状态或行为的一种能力;
-
单例模式:运行时期内始终保证某个类对应的只有一个实例对象
- 要让Java程序能够运行,那么就得让Java类(class文件)要被Java虚拟机(JVM)加载;
- Java类如果不被Java虚拟机加载,是不能正常运行的;
- 在项目中,如果向生产环境更新内容 ---更新的是class字节码文件
- 我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类已经被加载了;
- 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力;
- 在运行时期,通过反射可以动态地去获取类中的信息(类的信息,方法信息,构造器信息,字段等信息); 在运行期内 可以写程序通过反射机制去获取执行的那些对应类或者接口内部的结构
-
反射的作用
- 增加程序的灵活性,避免将程序写死到代码里(解除硬编码的问题);
- Java的反射机制它知道类的基本结构,可以动态的去获取类这样的结构的结构;
- 可以让程序员在不知道其它程序员会有什么类的时候就编写完成自己的代码;
- 反射的优点:灵活,功能强大(可以拿到私有的....);
- 反射的缺点:破坏封装,影响性能;
- 反射常用API
- 主要在java.lang.refelct包下
- java.lang.Class
- java.lang.reflect.Constructor ---构造器对应的类
- java.lang.reflect.Method ---方法(除了构造方法之外的方法)
- java.lang.reflect.Field --字段 成员变量
1、 Class类 和它的实例的产生: Class的实例是已经存在的类型,所以不能够直接new一个Class对象出来,而通过已知的类型和Class来获得
2、同一种类型不管通过什么方式得到Class的实例都是相等的;一个类型的字节码对象只有一份!
线程同步:同步监听对象 字节码对象来充当同步监听 始终保证都共享的是同一个同步监听对象
3、Class的实例就看成是Java中我们学过的所有的数据类型在JVM中存在的一种状态(字节码对象)
String.class int.class List.class int[].class int[][].class
- Class实例的获得方式
- 对象名.getClass() Object中,所有的对象都可以调用
- 类型.class 例如 String.class
- static Class<?> forName(String className) className是类或者接口的权限定名
- Class c1=String.class;
- Class c2="aaaa".getClass();
- Class c3=Class.forName(java.lang.String);
-
获得构造器结构的方式
-
条件就是构造方法中的形参的类型对应的Class实例
2. Constructor<?>[] getConstructors()
获得一个类中的所有的构造方法
3. Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
通过一个条件得到一个对应的构造方法对象
条件就是构造方法中的形成的类型对应的Class实例
4. Constructor<?>[] getDeclaredConstructors()
获得一个类中的所有的构造方法
注意 : 上面1 2 得到是公共的public修饰的;3 4 得到所有的,和访问权限无关
5 验证获得一个类中的默认无参数的构造方法(隐式的)
- 类型.class 例如 String.class
- 对象名.getClass() Object中,所有的对象都可以调用
---恢复内容结束---
Class实例的获得方式
- 类
- Class 类中的静态方法 static Class<?> forName(String className) className是类或者接口的权限定名
- 类型.class 例如 String.class
- 对象名.getClass() Object中,所有的对象都可以调用
-
Class实例
其实就是一些类型(类 接口 数组 基本数据类型 void)的字节码对象
Class 类的实例表示正在运行的 Java 应用程序中的类和接口(字节码对象);
枚举是一种类,注释(指的是注解Annotation)是一种接口;
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象;
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象;
注意 :
1、 Class类 和它的实例的产生: Class的实例是已经存在的类型,所以不能够直接new一个Class对象出来,而通过已知的类型和Class来获得
2、同一种类型不管通过什么方式得到Class的实例都是相等的;一个类型的字节码对象只有一份!
线程同步:同步监听对象 字节码对象来充当同步监听 始终保证都共享的是同一个同步监听对象
3、Class的实例就看成是Java中我们学过的所有的数据类型在JVM中存在的一种状态(字节码对象)
String.class int.class List.class int[].class int[][].class
-
获得构造器结构的方式
1. Constructor<T> getConstructor(Class<?>... parameterTypes)
通过一个条件得到一个对应的构造方法对象
条件就是构造方法中的形参的类型对应的Class实例
2. Constructor<?>[] getConstructors()
获得一个类中的所有的构造方法
3. Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
通过一个条件得到一个对应的构造方法对象
条件就是构造方法中的形成的类型对应的Class实例
4. Constructor<?>[] getDeclaredConstructors()
获得一个类中的所有的构造方法
注意 : 上面1 2 得到是公共的public修饰的;3 4 得到所有的,和访问权限无关
5 验证获得一个类中的默认无参数的构造方法(隐式的)
-
- lass类中有对应的方法
T newInstance() 创建此 Class 对象所表示的类的一个新实例
如同用一个带有一个空参数列表的 new 表达式实例化该类。
注意 : 只能够调用无参数的构造方法,
无参数的构造方法必须是有权限被访问到的
1. 获得构造器对象之后,通过构造器来创建对象
i. 获得Person类对应的Class实例
ii. 通过Class实例得到指定的构造方法
iii. 通过得到的构造方法对象来创建Person的实例
iv. 使用到了Constructor中的方法:
T newInstance(Object... initargs) 传入的实参
initargs 创建对象向构造方法中的传入的给对象那个初始化值的数据
构造器是私有的如何在外部创建对象?(单例模式外面还能创建对象吗?)
如果一个类的构造方法是私有的,通过反射得到构造方法来创建对象也会报错!
让访问权限失效
AccessibleObject
|-- Constructor,
|-- Field
|-- Method
它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力
void setAccessible(boolean flag)
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查
下列方法中,声明抛出InterruptedException类型异常的方法是
A.suspend()
B.resume()
C.sleep()
D.start()
正确答案
C
答案解析
[解析] 本题考查线程的基本操作。Java中提供了interrupt方法用来中断一个线程,当调用一个线程的interrupt方法时,即向该线程发送一个中断请求。需要注意的是,在调用线程的interrupt方法时,如果该线程由于调用了sleep方法或wait方法而正在处于阻塞状态,那么线程会抛出一个InterrupterException异常。因此,本题的正确答案是选项
思考? 为什么私有的成员在外部类中就不能访问呢? Java规定的
获得方法结构的方式
3. Method getDeclaredMethod(String name, Class<?>... parameterTypes)
4. Method[] getDeclaredMethods()
通过反射执行方法(重点)
通过反射调用方法
- 获得A对应的Class实例;
- 通过反射得到A中的指定的方法 t3
- 通过反射(Method类)来调用t3 方法
Method中的方法:
Object invoke(Object obj, Object... args)
注意 : m 只是一个方法的对应对象;
a 是A的一个实例
m 对应的这个方法,应该由m对应的方法所在的类的对象(a)来调用
调用方法的时候传入实际参数
验证调用私有的方法
① 得到 Class实例
② 通过① 得到指定的私有的方法 m
③ m. void setAccessible(true) ;
④ m.invoke(...);