Java笔记(27):反射

1、获取class文件对象的三种方式

 1 package cn.itcast_01;
 2
 3 public class Person {
 4     private String name;
 5     int age;
 6     public String address;
 7
 8     public Person() {
 9     }
10
11     private Person(String name) {
12         this.name = name;
13     }
14
15     Person(String name, int age) {
16         this.name = name;
17         this.age = age;
18     }
19
20     public Person(String name, int age, String address) {
21         this.name = name;
22         this.age = age;
23         this.address = address;
24     }
25
26     public void show() {
27         System.out.println("show");
28     }
29
30     public void method(String s) {
31         System.out.println("method " + s);
32     }
33
34     public String getString(String s, int i) {
35         return s + "---" + i;
36     }
37
38     private void function() {
39         System.out.println("function");
40     }
41
42     @Override
43     public String toString() {
44         return "Person [name=" + name + ", age=" + age + ", address=" + address
45                 + "]";
46     }
47
48 }

Person

 1 package cn.itcast_01;
 2
 3 /*
 4  * 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
 5  *
 6  * Person p = new Person();
 7  * p.使用
 8  *
 9  * 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
10  * Class类:
11  *         成员变量    Field
12  *         构造方法    Constructor
13  *         成员方法    Method
14  *
15  * 获取class文件对象的方式:
16  * A:Object类的getClass()方法
17  * B:数据类型的静态属性class
18  * C:Class类中的静态方法
19  *         public static Class forName(String className)
20  *
21  * 一般我们到底使用谁呢?
22  *         A:自己玩    任选一种,第二种比较方便
23  *         B:开发    第三种
24  *             为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
25  */
26 public class ReflectDemo {
27     public static void main(String[] args) throws ClassNotFoundException {
28         // 方式1
29         Person p = new Person();
30         Class c = p.getClass();
31
32         Person p2 = new Person();
33         Class c2 = p2.getClass();
34
35         System.out.println(p == p2);// false
36         System.out.println(c == c2);// true
37
38         // 方式2
39         Class c3 = Person.class;
40         // int.class;
41         // String.class;
42         System.out.println(c == c3);
43
44         // 方式3
45         // ClassNotFoundException
46         Class c4 = Class.forName("cn.itcast_01.Person");
47         System.out.println(c == c4);
48     }
49 }

2、通过反射获取无参构造方法并使用

 1 package cn.itcast_02;
 2
 3 import java.lang.reflect.Constructor;
 4
 5 import cn.itcast_01.Person;
 6
 7 /*
 8  * 通过反射获取构造方法并使用。
 9  */
10 public class ReflectDemo {
11     public static void main(String[] args) throws Exception {
12         // 获取字节码文件对象
13         Class c = Class.forName("cn.itcast_01.Person");
14
15         // 获取构造方法
16         // public Constructor[] getConstructors():所有公共构造方法
17         // public Constructor[] getDeclaredConstructors():所有构造方法
18         // Constructor[] cons = c.getDeclaredConstructors();
19         // for (Constructor con : cons) {
20         // System.out.println(con);
21         // }
22
23         // 获取单个构造方法
24         // public Constructor<T> getConstructor(Class<?>... parameterTypes)
25         // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
26         Constructor con = c.getConstructor();// 返回的是构造方法对象
27
28         // Person p = new Person();
29         // System.out.println(p);
30         // public T newInstance(Object... initargs)
31         // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
32         Object obj = con.newInstance();
33         System.out.println(obj);
34
35         // Person p = (Person)obj;
36         // p.show();
37     }
38 }

3、通过反射获取带参构造方法并使用

 1 package cn.itcast_02;
 2
 3 import java.lang.reflect.Constructor;
 4
 5 /*
 6  * 需求:通过反射去获取该构造方法并使用:
 7  * public Person(String name, int age, String address)
 8  *
 9  * Person p = new Person("林青霞",27,"北京");
10  * System.out.println(p);
11  */
12 public class ReflectDemo2 {
13     public static void main(String[] args) throws Exception {
14         // 获取字节码文件对象
15         Class c = Class.forName("cn.itcast_01.Person");
16
17         // 获取带参构造方法对象
18         // public Constructor<T> getConstructor(Class<?>... parameterTypes)
19         Constructor con = c.getConstructor(String.class, int.class,
20                 String.class);
21
22         // 通过带参构造方法对象创建对象
23         // public T newInstance(Object... initargs)
24         Object obj = con.newInstance("林青霞", 27, "北京");
25
26         System.out.println(obj);
27     }
28 }

4、通过反射获取私有构造方法并使用

 1 package cn.itcast_02;
 2
 3 import java.lang.reflect.Constructor;
 4
 5 /*
 6  * 需求:通过反射获取私有构造方法并使用
 7  * private Person(String name){}
 8  *
 9  * Person p = new Person("风清扬");
10  * System.out.println(p);
11  */
12 public class ReflectDemo3 {
13     public static void main(String[] args) throws Exception {
14         // 获取字节码文件对象
15         Class c = Class.forName("cn.itcast_01.Person");
16
17         // 获取私有构造方法对象
18         // NoSuchMethodException:每个这个方法异常
19         // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
20         Constructor con = c.getDeclaredConstructor(String.class);
21
22         // 用该私有构造方法创建对象
23         // IllegalAccessException:非法的访问异常。
24         // 暴力访问
25         con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
26         Object obj = con.newInstance("风清扬");
27
28         System.out.println(obj);
29     }
30 }

5、通过反射获取成员变量并使用

 1 package cn.itcast_03;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5
 6 /*
 7  * 通过发生获取成员变量并使用
 8  */
 9 public class ReflectDemo {
10     public static void main(String[] args) throws Exception {
11         // 获取字节码文件对象
12         Class c = Class.forName("cn.itcast_01.Person");
13
14         // 获取所有的成员变量
15         // Field[] fields = c.getFields();
16         // Field[] fields = c.getDeclaredFields();
17         // for (Field field : fields) {
18         // System.out.println(field);
19         // }
20
21         /*
22          * Person p = new Person(); p.address = "北京"; System.out.println(p);
23          */
24
25         // 通过无参构造方法创建对象
26         Constructor con = c.getConstructor();
27         Object obj = con.newInstance();
28         System.out.println(obj);
29
30         // 获取单个的成员变量
31         // 获取address并对其赋值
32         Field addressField = c.getField("address");
33         // public void set(Object obj,Object value)
34         // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
35         addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
36         System.out.println(obj);
37
38         // 获取name并对其赋值
39         // NoSuchFieldException
40         Field nameField = c.getDeclaredField("name");
41         // IllegalAccessException
42         nameField.setAccessible(true);
43         nameField.set(obj, "林青霞");
44         System.out.println(obj);
45
46         // 获取age并对其赋值
47         Field ageField = c.getDeclaredField("age");
48         ageField.setAccessible(true);
49         ageField.set(obj, 27);
50         System.out.println(obj);
51     }
52 }

6、通过反射获取成员方法并使用

 1 package cn.itcast_04;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Method;
 5
 6 public class ReflectDemo {
 7     public static void main(String[] args) throws Exception {
 8         // 获取字节码文件对象
 9         Class c = Class.forName("cn.itcast_01.Person");
10
11         // 获取所有的方法
12         // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
13         // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
14         // for (Method method : methods) {
15         // System.out.println(method);
16         // }
17
18         Constructor con = c.getConstructor();
19         Object obj = con.newInstance();
20
21         /*
22          * Person p = new Person(); p.show();
23          */
24
25         // 获取单个方法并使用
26         // public void show()
27         // public Method getMethod(String name,Class<?>... parameterTypes)
28         // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
29         Method m1 = c.getMethod("show");
30         // obj.m1(); // 错误
31         // public Object invoke(Object obj,Object... args)
32         // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
33         m1.invoke(obj); // 调用obj对象的m1方法
34
35         System.out.println("----------");
36         // public void method(String s)
37         Method m2 = c.getMethod("method", String.class);
38         m2.invoke(obj, "hello");
39         System.out.println("----------");
40
41         // public String getString(String s, int i)
42         Method m3 = c.getMethod("getString", String.class, int.class);
43         Object objString = m3.invoke(obj, "hello", 100);
44         System.out.println(objString);
45         // String s = (String)m3.invoke(obj, "hello",100);
46         // System.out.println(s);
47         System.out.println("----------");
48
49         // private void function()
50         Method m4 = c.getDeclaredMethod("function");
51         m4.setAccessible(true);
52         m4.invoke(obj);
53     }
54 }

7、通过反射运行配置文件内容

配置文件class.txt的内容:

className=cn.itcast.test.Student
methodName=love

1 package cn.itcast.test;
2
3 public class Student {
4     public void love() {
5         System.out.println("爱生活,爱烨儿");
6     }
7 }
1 package cn.itcast.test;
2
3 public class Teacher {
4     public void love() {
5         System.out.println("爱生活,爱青霞");
6     }
7 }
1 package cn.itcast.test;
2
3 public class Worker {
4     public void love() {
5         System.out.println("爱生活,爱娘子");
6     }
7 }
 1 package cn.itcast.test;
 2
 3 import java.io.FileReader;
 4 import java.lang.reflect.Constructor;
 5 import java.lang.reflect.Method;
 6 import java.util.Properties;
 7
 8 /*
 9  * 通过配置文件运行类中的方法
10  *
11  * 反射:
12  *         需要有配置文件配合使用。
13  *         用class.txt代替。
14  *         并且你知道有两个键。
15  *             className
16  *             methodName
17  */
18 public class Test {
19     public static void main(String[] args) throws Exception {
20         // 反射前的做法
21         // Student s = new Student();
22         // s.love();
23         // Teacher t = new Teacher();
24         // t.love();
25         // Worker w = new Worker();
26         // w.love();
27         // 反射后的做法
28
29         // 加载键值对数据
30         Properties prop = new Properties();
31         FileReader fr = new FileReader("class.txt");
32         prop.load(fr);
33         fr.close();
34
35         // 获取数据
36         String className = prop.getProperty("className");
37         String methodName = prop.getProperty("methodName");
38
39         // 反射
40         Class c = Class.forName(className);
41
42         Constructor con = c.getConstructor();
43         Object obj = con.newInstance();
44
45         // 调用方法
46         Method m = c.getMethod(methodName);
47         m.invoke(obj);
48     }
49 }

8、通过反射越过泛型检查

 1 package cn.itcast.test;
 2
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 import java.util.ArrayList;
 6
 7 /*
 8  * 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
 9  */
10 public class ArrayListDemo {
11     public static void main(String[] args) throws NoSuchMethodException,
12             SecurityException, IllegalAccessException,
13             IllegalArgumentException, InvocationTargetException {
14         // 创建集合对象
15         ArrayList<Integer> array = new ArrayList<Integer>();
16
17         // array.add("hello");
18         // array.add(10);
19
20         Class c = array.getClass(); // 集合ArrayList的class文件对象
21         Method m = c.getMethod("add", Object.class);
22
23         m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
24         m.invoke(array, "world");
25         m.invoke(array, "java");
26
27         System.out.println(array);
28     }
29 }

9、通过反射写一个通用的设置某个对象的某个属性为指定的值

 1 package cn.itcast.test;
 2
 3 public class ToolDemo {
 4     public static void main(String[] args) throws NoSuchFieldException,
 5             SecurityException, IllegalArgumentException, IllegalAccessException {
 6         Person p = new Person();
 7         Tool t = new Tool();
 8         t.setProperty(p, "name", "林青霞");
 9         t.setProperty(p, "age", 27);
10         System.out.println(p);
11         System.out.println("-----------");
12
13         Dog d = new Dog();
14
15         t.setProperty(d, "sex", ‘男‘);
16         t.setProperty(d, "price", 12.34f);
17
18         System.out.println(d);
19     }
20 }
21
22 class Dog {
23     char sex;
24     float price;
25
26     @Override
27     public String toString() {
28         return sex + "---" + price;
29     }
30 }
31
32 class Person {
33     private String name;
34     public int age;
35
36     @Override
37     public String toString() {
38         return name + "---" + age;
39     }
40 }

10、动态代理的概述和实现

 1 package cn.itcast_06;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5
 6 public class MyInvocationHandler implements InvocationHandler {
 7     private Object target; // 目标对象
 8
 9     public MyInvocationHandler(Object target) {
10         this.target = target;
11     }
12
13     @Override
14     public Object invoke(Object proxy, Method method, Object[] args)
15             throws Throwable {
16         System.out.println("权限校验");
17         Object result = method.invoke(target, args);
18         System.out.println("日志记录");
19         return result; // 返回的是代理对象
20     }
21 }
 1 package cn.itcast_06;
 2
 3 /*
 4  * 用户操作接口
 5  */
 6 public interface UserDao {
 7     public abstract void add();
 8
 9     public abstract void delete();
10
11     public abstract void update();
12
13     public abstract void find();
14 }
 1 package cn.itcast_06;
 2
 3 public class UserDaoImpl implements UserDao {
 4
 5     @Override
 6     public void add() {
 7         System.out.println("添加功能");
 8     }
 9
10     @Override
11     public void delete() {
12         System.out.println("删除功能");
13     }
14
15     @Override
16     public void update() {
17         System.out.println("修改功能");
18     }
19
20     @Override
21     public void find() {
22         System.out.println("查找功能");
23     }
24
25 }
 1 package cn.itcast_06;
 2
 3 import java.lang.reflect.Proxy;
 4
 5 public class Test {
 6     public static void main(String[] args) {
 7         UserDao ud = new UserDaoImpl();
 8         ud.add();
 9         ud.delete();
10         ud.update();
11         ud.find();
12         System.out.println("-----------");
13         // 我们要创建一个动态代理对象
14         // Proxy类中有一个方法可以创建动态代理对象
15         // public static Object newProxyInstance(ClassLoader loader,Class<?>[]
16         // interfaces,InvocationHandler h)
17         // 我准备对ud对象做一个代理对象
18         MyInvocationHandler handler = new MyInvocationHandler(ud);
19         UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
20                 .getClassLoader(), ud.getClass().getInterfaces(), handler);
21         proxy.add();
22         proxy.delete();
23         proxy.update();
24         proxy.find();
25         // System.out.println("-----------");
26         //
27         // StudentDao sd = new StudentDaoImpl();
28         // MyInvocationHandler handler2 = new MyInvocationHandler(sd);
29         // StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
30         // .getClassLoader(), sd.getClass().getInterfaces(), handler2);
31         // proxy2.login();
32         // proxy2.regist();
33     }
34 }
时间: 2024-07-28 15:25:12

Java笔记(27):反射的相关文章

Java笔记:反射

一.基础知识 Class是泛型超类,封装了类或接口运行时的状态.Class是Java中的反射中心,可以在运行时查找类的信息. class Solution { public static void main(String[] args) throws ClassNotFoundException { Class c = String.class;//通过类文字获取 c = "Hello World".getClass();//通过getClass获取 c = Class.forName

Core Java 笔记

Core Java 的读书笔记,持续更新中... Core Java笔记 1.对象与类 Core Java笔记 2.继承 Core Java笔记 3.反射

java笔记--反射机制之基础总结与详解

一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象. 它提供了在运行时检查对象属性的方法,这些属性包括它的成员和类型信息. 更重要的是Class对象是所有反射API的入口. Class类是泛型类,可以使用@SuppressWarnings("unchecked")忽略泛型或者使用Class<V>类型. 获得Class对象的5种

java笔记--反射进阶之总结与详解

一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是我们仍然可以用java的反射机制来 修改类的私有域,由于修改类的私有域会破坏Java"封装"的特性,故请慎重操作. 主要技术:     Field类提供有关类或接口的单个字段的信息,以及对它的动态访问权限.     访问的字段可能是一个类(静态)字段或实例字段.             常

Java语言的反射机制 笔记 摘自 http://blog.csdn.net/kaoa000/article/details/8453371

在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的.这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制. 1.Java 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类.在运行时构造任意一个类的对象.在运行时判断任意一个类所具有的成员变量和方法.在运行时调用任意一个对象的方法 2.Reflection 是Java被视为动态(或准动态)语言的一个关键性质.

第16篇-JAVA 类加载与反射

第16篇-JAVA 类加载与反射 每篇一句 :敢于弯曲,是为了更坚定的站立 初学心得: 追求远中的欢声笑语,追求远中的结伴同行 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-05-12| JAVA 类加载与反射 ] 1.类加载 类加载器负责将 .class 文件(可能在磁盘上, 也可能在网络上) 加载到内存中, 并为之生成对应的 java.lang.Class 对象 当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载.连接.初始化三个步骤来对该类进行初始化,如果没

Java中的反射机制

Java反射的概念 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制 Java反射机制主要提供下面几种用途: 1.在运行时判断任意一个对象所属的类 2.在运行时构造任意一个类的对象 3.在运行时判断任意一个类所具有的成员变量和方法 4.在运行时调用任意一个对象的方法 首先看一个简单的例子,通过这个例子来理解Java的反射机制是如何工作的 i

java中的反射

一.什么是反射 简单来说,java反射机制其实就是I/O流的一种封装版,用来快速读取硬盘上的class文件.class文件相当于一个身份证,JVM在操作某一个对象时,需要根据身份证获得对象拥有的属性和拥有的功能及方法.这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制. 二.官方提供的反射机制API: class文件: java.lang.reflect.Class类:描述内存中class文件 属性(数据存储单位): java.lang.reflect.Field类:描述内存

Java笔记(9)

JSP 存在两种 开发模式 Model1 : JSP + JavaBean * 不适合开发业务逻辑特别复杂web应用 ----- 业务逻辑复杂,控制代码多,而在jsp中编写控制代码,十分不便 Model2 : JSP + JavaBean + Servlet 符合MVC设计模式 JSP(View视图功能):负责页面显示 JavaBean(Model 模型功能):负责数据封装和处理 Servlet(Controller 控制器功能):连接模型和视图,对整个业务流程进行控制,调用JavaBean封装