Java反射机制

Java反射机制

反射的内容:

1、Class类的使用;

2、动态加载类

3、方法的反射

4获取成员变量属性;

5通过反射了解集合泛型的本质。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一:class类的使用

   Java中,万事万物皆对象,类也是对象,任何一个类都是java.lang.Class类的实例对象,这个对象我们为该类的类类型。

注:静态成员(静态成员属于类)与普通数据类型(但有对应的包装类弥补)不是对象

 

(1)反射机制获取类有三种方法

注:功能性的类尽量使用动态加载,并对新添的类实现功能性接口(标准),这样就不用重新编译

①forName()forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装(最建议)

注:这种方法不仅表示了类的类类型,还代表了动态加载类区分编译、运行编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

类名.class

对象.getClass()

 

Person类为例:

public void test1() throws Exception {

// 方式一

Class clazz1 = Class.forName("reflect.Person");

// 方式二

Class clazz2 = Person.class;

// 方式三

Person p1 = new Person();

Class clazz3 = p1.getClass();

}

 

(2)通过Class类获取类的一些信息

1. getName()类的名称(全名,全限定名)

2 getSimpleName()类的的简单名称(不带包名)

3. getModifiers(); 类的的修饰符

4.创建对象

无参数构造创建对象

newInstance()

5. 获取指定参数的构造器对象,并可以使用Constructor对象创建一个实例

Constructor<T> getConstructor(Class<?>... parameterTypes)

 

例:

private static void test2() throws Exception {

 

Class clazz1 = Class.forName("reflect.Person");

// 获取类的名称

String name = clazz1.getName();

System.out.println(name); // reflect.Person

// 获取类的简单名称

System.out.println(clazz1.getSimpleName()); // Person

// 获取类的修饰符

int modifiers = clazz1.getModifiers();

System.out.println(modifiers);

// 构建对象(默认调用无参数构造.)

Object ins = clazz1.newInstance();

Person p = (Person) ins;

System.out.println(p);

// 获取指定参数的构造函数

Constructor<?> con = clazz1.getConstructor(String.class, int.class);

// 使用Constructor创建对象.

Object p1 = con.newInstance("jack", 28);

System.out.println(((Person) p1).getName());

}

 

 

 在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于java.lang.reflect包中

Class类:代表一个类,位于java.lang包下。

Field类:代表类的成员变量(成员变量也称为类的属性)。

Method类:代表类的方法。

Constructor类:代表类的构造方法。

Array类:提供了动态创建数组,以及访问数组的元素的静态方法

二:动态加载类

   1.区分动态加载和静态加载

静态加载类,是编译时刻加载;

动态加载类,是运行时刻加载

   2、new创建对象:是静态加载类,在编译时刻就需要加载所有的【可能使用

      到的类】。有一个类有问题(如不存在),都不能通过编译,会报错。通

      过动态加载类可以解决该问题。

   3、Class.forName():动态加载类,当用到一个类时,才进行加载。                    

 

三:方法的反射:

①要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型

②获取方法 由名称和参数列表来决定,getMethod获取的是public方法,getDelcaredMethod获取自己声明的方法

 

1通过Class类获取类型中的方法的信息

1.获取公共方法包括继承父类的方法

getMethods();     返回一个数组,元素类型是Method

2.获取指定参数的公共方法

getMethod("setName", String.class);

3.获得所有的方法,包括私有

Method[] getDeclaredMethods();  

4.获得指定参数的方法,包括私有

Method getDeclaredMethod(String name, Class<?>... parameterTypes)

 

例:

/**

 * 获取公有方法.

 * @throws Exception

 * */

private static void test3() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

// 1.获取非私用方法(包括父类继承的方法)

Method[] methods = clazz1.getMethods();

System.out.println(methods.length);

for (Method m : methods) {

// System.out.println(m.getName());

if ("eat".equals(m.getName())) {

m.invoke(clazz1.newInstance(), null);

}

}

}

 

/**

 * 获取指定方法签名的方法

 * @throws Exception

 * */

private static void test4() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

// 获取指定名称的函数

Method method1 = clazz1.getMethod("eat", null);

method1.invoke(new Person(), null);

}

 

 

/**

 * 获取指定方法名且有参数的方法

 * @throws Exception

 * */

private static void test5() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

Method method = clazz1.getMethod("eat", String.class);

method.invoke(new Person(), "包子");

}

 

/**

 * 获取指定方法名,参数列表为空的方法.

 * @throws Exception

 * */

private static void test4() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

// 获取指定名称的函数

Method method1 = clazz1.getMethod("eat", null);

method1.invoke(new Person(), null);

}

 

2)反射方法

/**

 * 反射静态方法

 * @throws Exception

 * */

private static void test7() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

Method method = clazz1.getMethod("play", null);

method.invoke(null, null);

}

 

/**

 * 访问私有方法 暴力反射

 * @throws Exception

 * */

private static void test6() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

Method method = clazz1.getDeclaredMethod("movie", String.class);

method.setAccessible(true);

method.invoke(new Person(), "张艺谋");

}

 

 

四:通过Class类获取类型中的属性信息

1.获取公有属性

Field[] getFields()  

2.获取指定参数的公共属性

Field getField(String name)  

3.获取所有的属性

Field[] getDeclaredFields()  

4.获取指定参数的属性,包括私

Field getDeclaredField(String name)

 

例:

/**

 * 获取公有的属性

 * */

private static void test8() throws Exception {

 Class clazz1 =Class.forName("reflect.Person");

Field[] fields = clazz1.getFields();

Person p = new Person();

System.out.println(fields.length);

for (Field f : fields) {

System.out.println(f.getName());

if ("name".equals(f.getName())) {

System.out.println(f.getType().getName());

f.set(p, "jack");

}

}

System.out.println(p.getName());

 

}

 

/**

 * 获取私有的属性

 * @throws Exception

 * */

private static void test9() throws Exception {

Class clazz1 = Class.forName("reflect.Person");

Field field = clazz1.getDeclaredField("age");

System.out.println(field.getName());

field.setAccessible(true);

Person p = new Person();

field.set(p, 100);

System.out.println(p.getAge());

}

 

五:通过反射了解集合泛型的本质

--java中集合的泛型是防止错误输入的;

--只在编译阶段有效,绕过编译就无效了,我们可以通过方法的反射来操作,绕过编译

:

ArrayList list1=new ArrayList();

ArrayList<String> list2=new ArrayList<String>();

Class c1=list1.getClass();

Class c2=list2.getClass();

System.out.print(c1==c2); //true

Method m=c2.getMethod("add",Object.class);

m.invoke(list2,20);//list2集合中添加一个int 型的值;绕过编译,这时就不能直接foreach list2集合,会报类型转换错误

 

 

------录制视频的老师say:如果想成为大牛,就一定会用到反射机制,编写一些工具,就比如用于javaweb开发的三大框架......hahahahaha~~~,目前只希望能看懂大牛们的代码==

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值