03.反射杂谈

1.什么是反射?
反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为Java反射机制。
 
2.Java反射机制的作用
1). 在运行时判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任意一个对象的方法
 
3.java反射机制提供了什么功能?
1). 在运行时能够判断任意一个对象所属的类
2). 在运行时构造任意一个类的对象
3). 在运行时判断任意一个类所具有的成员变量和方法
4). 在运行时调用任一对象的方法
5). 在运行时创建新类对象
 
4.哪里用到反射机制?
各种框架用的最多的就是反射
加载驱动
读取配置文件
 
5.运用反射的优缺点
优点:
    反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:
   (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可变参数);-----(有返回值的)
 
7.反射重要借助哪四个类?
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")
 
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方法来获取/设置字段的值了。
 
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对象有多种方式:
调用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>类提供了几个方法获取类的属性。

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)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
public Constructor<?>[]
 getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
public Constructor<T>
 getDeclaredConstructor(Class<?>...
 parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[]
 getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法
posted @ 2019-04-19 21:21  69之王  阅读(95)  评论(0编辑  收藏  举报