03.反射杂谈
1.什么是反射?
反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为Java反射机制。
反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为Java反射机制。
2.Java反射机制的作用
1). 在运行时判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任意一个对象的方法
1). 在运行时判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任意一个对象的方法
3.java反射机制提供了什么功能?
1). 在运行时能够判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任一对象的方法
5). 在运行时创建新类对象
1). 在运行时能够判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任一对象的方法
5). 在运行时创建新类对象
4.哪里用到反射机制?
各种框架用的最多的就是反射
加载驱动
读取配置文件
各种框架用的最多的就是反射
加载驱动
读取配置文件
5.运用反射的优缺点
优点:
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:
(1)性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
(2)使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
优点:
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:
(1)性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
(2)使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
6.如何使用java的反射?
a. 通过一个全限类名创建一个对象
1)、Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
2)、类名.class; 获取Class<?> clz 对象
3)、对象.getClass();
b. 获取构造器对象,通过构造器new出一个对象
1). Class.getConstructor([String.class]);
2). Con.newInstance([参数]);
c. 通过class对象创建一个实例对象(就相当与new类名()无参构造器)
1). Class.newInstance();
d. 通过class对象获得一个属性对象
1)、Field c=clz.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
2)、Field c=clz.getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段 e.
e、通过class对象获得一个方法对象
1). Class.getMethod(“方法名”,class……parameaType);(只能获取公共的)
2). Class.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
3) M.setAccessible(true);(让私有的方法可以执行)
f. 让方法执行
1). Method.invoke(obj实例对象,obj可变参数);-----(有返回值的)
a. 通过一个全限类名创建一个对象
1)、Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
2)、类名.class; 获取Class<?> clz 对象
3)、对象.getClass();
b. 获取构造器对象,通过构造器new出一个对象
1). Class.getConstructor([String.class]);
2). Con.newInstance([参数]);
c. 通过class对象创建一个实例对象(就相当与new类名()无参构造器)
1). Class.newInstance();
d. 通过class对象获得一个属性对象
1)、Field c=clz.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
2)、Field c=clz.getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段 e.
e、通过class对象获得一个方法对象
1). Class.getMethod(“方法名”,class……parameaType);(只能获取公共的)
2). Class.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
3) M.setAccessible(true);(让私有的方法可以执行)
f. 让方法执行
1). Method.invoke(obj实例对象,obj可变参数);-----(有返回值的)
7.反射重要借助哪四个类?
1)、Class:类的对象;
2)、Constructor:类的构造方法
3)、Field:类中的属性对象
4)、Method:类中的方法对象
1)、Class:类的对象;
2)、Constructor:类的构造方法
3)、Field:类中的属性对象
4)、Method:类中的方法对象
8.获得一个类的类对象有哪些方式?
方法1:类型.class,例如:String.class
方法2:对象.getClass(),例如:"hello".getClass()
方法3:Class.forName(),例如:Class.forName("java.lang.String")
方法2:对象.getClass(),例如:"hello".getClass()
方法3:Class.forName(),例如:Class.forName("java.lang.String")
9.如何通过反射创建对象?
方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");
10.如何通过反射获取和设置对象私有字段的值?
可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。
可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。
11.如何通过反射调用对象的方法?
import java.lang.reflect.Method;
class MethodInvokeTest {
public static void main(String[] args) throws Exception {
String str = "hello";
Method m = str.getClass().getMethod("toUpperCase");
System.out.println(m.invoke(str)); // HELLO
}
}
12.反射中,Class.forName 和 ClassLoader 区别。
Class.forName(className)方法,其实调用的方法是Class.forName(className,true,classloader);注意看第2个boolean参数,它表示的意思,在loadClass后必须初始化。比较下我们前面准备jvm加载类的知识,我们可以清晰的看到在执行过此方法后,目标对象的 static块代码已经被执行,static参数也已经被初始化。
再看ClassLoader.loadClass(className)方法,其实他调用的方法是ClassLoader.loadClass(className,false);还是注意看第2个 boolean参数,该参数表示目标对象被装载后不进行链接,这就意味这不会去执行该类静态块中间的内容
13.如何获取类的class对象
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
获取类的Class对象有多种方式:
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
获取类的Class对象有多种方式:
调用getClass
Boolean var1 = true;
Class<?> classType2 = var1.getClass();
System.out.println(classType2);
输出:class java.lang.Boolean
运用.class 语法
Class<?> classType4 = Boolean.class;
System.out.println(classType4);
输出:class java.lang.Boolean
运用static method Class.forName()
Class<?> classType5 = Class.forName("java.lang.Boolean");
System.out.println(classType5);
输出:class java.lang.Boolean
运用primitive wrapper classes的TYPE 语法
这里返回的是原生类型,和Boolean.class返回的不同
Class<?> classType3 = Boolean.TYPE;
System.out.println(classType3); 输出:boolean
14.如何获取类的fields
可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。JAVA 的Class<T>类提供了几个方法获取类的属性。
可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。JAVA 的Class<T>类提供了几个方法获取类的属性。
public FieldgetField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
public Field[]
getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
public FieldgetDeclaredField(Stringname)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
public Field[]
getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
15.如何获取类的constructor
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例
,Class<T>类提供了几个方法获取类的构造器。
public Constructor<T>
getConstructor(Class<?>...
parameterTypes)
getConstructor(Class<?>...
parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
public Constructor<?>[]
getConstructors()
getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
public Constructor<T>
getDeclaredConstructor(Class<?>...
parameterTypes)
getDeclaredConstructor(Class<?>...
parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[]
getDeclaredConstructors()
getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法