代码已上传至Github,有兴趣的同学可以下载来看看:https://github.com/ylw-github/Java-DesignMode
1. 什么是Java反射机制
就是正在运行,动态获取这个类的所有信息。
2. 反射机制的作用
3. 反射机制的应用场景
4. 反射机制获取类的三种方式
第一种方式:使用Class.forName的方式
Class class1 = Class.forName("Employee")
第二种方式:java中每个类型都有class 属性.
Class class2 = Employee.class;
第三种方式:java语言中任何一个java对象都有getClass 方法.
Employee e = new Employee(); Class class3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
注意抛出的异常:
5. 反射创建对象的方式
方式一:创建此Class 对象所表示的类的一个新实例 调用了Employee的无参数构造方法.
Class<?> forName = Class.forName("com.ylw.reflect.Employee"); Object newInstance = forName.newInstance();
方式二:实例化有参构造函数
Class<?> forName1 = Class.forName("com.ylw.reflect.Employee"); Constructor<?> constructor = forName1.getConstructor(String.class, String.class); Employee newInstance1 = (Employee) constructor.newInstance("张三", "男");
注意抛出的异常:
6. 反射创建API
方法名称 | 作用 |
getDeclaredMethods [] | 获取该类的所有方法 |
getReturnType() | 获取该类的返回值 |
getParameterTypes() | 获取传入参数 |
getDeclaredFields() | 获取该类的所有字段 |
setAccessible | 允许访问私有成员 |
7. 使用反射为类私有属性赋值
Employee类:
package com.ylw.reflect; public class Employee { private String name; private String sex; public Employee() { } public Employee(String name, String sex) { this.name = name; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } }
测试方法:
public static void setValue() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { Class<?> classUser = Class.forName("com.ylw.reflect.Employee"); //Test1: 获取到当前的所有属性 Field[] fields = classUser.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); } //Test2: 获取当前所有的方法 Method[] declaredMethods = classUser.getDeclaredMethods(); for (Method method : declaredMethods) { System.out.println(method.getName()); } //1. 为Employee对象私有属性赋值 Employee employee = (Employee) classUser.newInstance(); Field nameField = classUser.getDeclaredField("name"); // 标记为true 允许反射赋值 nameField.setAccessible(true); nameField.set(employee, "张三"); Field sexField = classUser.getDeclaredField("sex"); // 标记为true 允许反射赋值 sexField.setAccessible(true); sexField.set(employee, "男"); System.out.println("使用反射机制给Employee赋值为:"+ employee.toString()); }
运行结果:
8. JDBC反射加载驱动
// 加载驱动类 Class.forName("com.mysql.jdbc.Driver"); // 通过DriverManager获取数据库连接 String url = "jdbc:mysql://192.168.1.150/test"; String user = "teamtalk"; String password = "123456"; Connection connection = (Connection) DriverManager.getConnection( url, user, password); PreparedStatement statement = (PreparedStatement) connection.prepareStatement( "insert persion (name, age) value (?, ?)"); statement.setString(1, "hdu"); statement.setInt(2, 21); statement.executeUpdate(); ResultSet resultSet = statement.executeQuery("select * from persion"); // 操作ResultSet结果集 while (resultSet.next()) { // 第一种获取字段方式 System.out.println(resultSet.getString(1) + " " + resultSet.getString(2) + " " + resultSet.getString(3)); } // 关闭数据库连接 resultSet.close(); statement.close(); connection.close();
对于Class.forName("com.mysql.jdbc.Driver")
涉及到了JVM类加载的机制,可以参考文章:《设计模式系列教程(02) - 反射机制(二)》一文。
9. 如何禁止使用反射机制初始化
方法:将构造函数为私有化!
PrivateEmployee类:
package com.ylw.reflect; public class PrivateEmployee { private String name; private String sex; private PrivateEmployee() { } private PrivateEmployee(String name, String sex) { this.name = name; this.sex = sex; } // getter setter... }
例如:把上述的Employee构造函数设置为私有类,会抛异常:
private static void testPrivateClazz() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { Class<?> classUser = Class.forName("com.ylw.reflect.PrivateEmployee"); //Test1: 获取到当前的所有属性 Field[] fields = classUser.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); } //Test2: 获取当前所有的方法 Method[] declaredMethods = classUser.getDeclaredMethods(); for (Method method : declaredMethods) { System.out.println(method.getName()); } //1. 为Employee对象私有属性赋值 PrivateEmployee employee = (PrivateEmployee) classUser.newInstance(); Field nameField = classUser.getDeclaredField("name"); // 标记为true 允许反射赋值 nameField.setAccessible(true); nameField.set(employee, "张三"); Field sexField = classUser.getDeclaredField("sex"); // 标记为true 允许反射赋值 sexField.setAccessible(true); sexField.set(employee, "男"); System.out.println("使用反射机制给Employee赋值为:"+ employee.toString()); }
抛异常:
name sex toString getName setName setSex Exception in thread "main" getSex java.lang.IllegalAccessException: Class com.ylw.reflect.RefelectDemo can not access a member of class com.ylw.reflect.PrivateEmployee with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.Class.newInstance(Class.java:436) at com.ylw.reflect.RefelectDemo.testPrivateClazz(RefelectDemo.java:92) at com.ylw.reflect.RefelectDemo.main(RefelectDemo.java:12) Process finished with exit code 1
总结