代码已上传至Github,有兴趣的同学可以下载来看看:https://github.com/ylw-github/Java-DesignMode
1. 什么是Java反射机制就是正在运行,动态获取这个类的所有信息。
2. 反射机制的作用-
反编译:.class–>.java
-
通过反射机制访问java对象的属性,方法,构造方法等
-
Jdbc 加载驱动
-
Spring IOC
-
框架
第一种方式:使用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)
注意抛出的异常:
方式一:创建此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("张三", "男");
注意抛出的异常:
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());
}
运行结果:
// 加载驱动类
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) - 反射机制(二)》一文。
方法:将构造函数为私有化!
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
总结