基础概念
什么是反射
运行时动态获取类的内部信息的一种方式。
反射的作用
1. 可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器
2. 可以创建对象并访问任意对象方法和属性等
Class类加载
类加载到内存:Java将磁盘类文件加载到内存中为一个对象(实例),这个对象是Class类的实例
Class实例代表Java中的类型
1. 获得基本类型实例
int.class
long.class ....
2. 获得类类型(Class)实例
Class cls = String.class;
Class cls = Class.forName(“java.lang.String”);
Class cls = “abc”.getClass();
以上方法获得cls是同一个对象,就是Sting类内存加载的结果
典型应用
IDE的提示、JavaBean的拷贝、简单工厂
通过反射创建对象实例
案例
public static Object create(String classname) { try{ // 1、加载类 Class cls = Class.forName(classname); // 2、创建类实例 Object obj = cls.newInstance(); return obj; } catch(Exception e){ throw new RuntimeException("创建对象失败", e); } }
class.forName作用
要求JVM查找并加载指定的类(加载dao方法区中),也就是说JVM会执行该类的静态代码段。
当直接new对象实例化后该类的静态代码块也会被执行,但是这样不利于动态读取配置文件创建连接,因此一般都使用Class.forName的形式。
JDBC加载驱动类
常见的是JDBC连接数据库的时候加载驱动类。注册一个数据库驱动。class.forname(“oracle.jdbc.driver.OracleDriver”);该代码是加载oracle驱动类,完成驱动的注册。执行驱动类的一些静态代码块。
静态代码块的主要内容是:
DriverManager.registerDriver(new OracleDriver());向DriverManager注册自己。(所谓注册就是创建Driver实例,添加到驱动列表中)。
注册成功后,就可以与数据库进行连接。
DriverManager.getConnection(url, user, password);
这个方法主要实现的是找到注册时创建的oracleDriver对象,调用OracleDriver的connect(url)来实现数据库的连接。对数据库操作时,OracleDriver调用Oracle对Connection,Statement,ResultSet几个接口的实现类来完成功能。
OracleDriver这个类是用来管理Connection,Statement,ResultSet这几个接口的
DriverManger是用来管理OracleDrier类的。
Class类的相关方法
Calss(类类型):用于存储类的信息,诸如类名、有哪些属性,方法,构造器,父类型
Class类的实例表示正在运行的Java类或者接口。任何Java的类或者接口都是Class类的一个实例。
Class clazz=String.class;
clazz.getName() 类名:java.lang.String
clazz.getSimpleName() 简单类名:String
clazz.getSuperclass().getName() 父类型名称:java.lang.Object
Class[] classes=clazz.getInterfaces(); 获取所实现的接口信息,返回值是数组类型
Method[] methods=clazz.getMethods(); 获取该类拥有的public方法信息
clazz.getDeclaredMethod(方法名,参数类型); 获取某个具体的方法
Field[] fields=clazz.getFields(); 获取public属性信息
Field[] fields=clazz.getDeclaredFields(); 获取所有属性
Field field=clazz.getDeclaredField("name"); 获取一个具体的属性
public class BaseClass { int id; private String name; public double grade; public BaseClass() { } public BaseClass(int id, String name, double grade) { super(); this.id = id; this.name = name; this.grade = grade; } public void fun1() { System.out.println("无返回值,无参数的方法"); } public String fun2(int a) { return this.name + "," + a; } }
Filed类的相关方法
field.getModifiers() 返回该属性的修饰符信息(private static final...),返回是整数
Modifier.toString(field.getModifiers()) 把整数转换成相应的private public..
field.getType().getSimpleName() 属性类型
field.getName() 属性名
Field field=clazz.getDeclaredField(属性名"); 获得某一个具体的属性值
field.setAccessible(true); 允许访问私有属性
Object value=field.get(具体的对象引用obj); 获取具体对象obj中该属性值
field.set(obj, "李四"); 对具体对象object的属性设置值”张三”,该属性就是field对应的属性
public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.org.qin.test.BaseClass"); Field[] fields = clazz.getDeclaredFields(); // 访问BaseClass的属性信息,修饰符 类型 属性名 for(Field field : fields){ System.out.print(Modifier.toString(field.getModifiers()) + " " + field.getType().getSimpleName() + " " + field.getName()); System.out.println(); } BaseClass obj = new BaseClass(1, "张三", 2); // 获取某一个具体的属性 Field field = clazz.getDeclaredField("name"); // 允许访问私有属性 field.setAccessible(true); // 获取属性中的值 Object value = field.get(obj); System.out.println(value); // 为对象的属性赋值 field.set(obj, "李四"); System.out.println(field.get(obj)); }
Method类的相关方法
method.getReturnType() 方法返回值类型
method.getName() 方法名
Class[] pTypes=method.getParameterTypes(); 方法参数类型
method.invoke(obj, new Class[]{}); 调用某个具体的方法
public static void main(String[] args) throws Exception { Class clazz = BaseClass.class; Method[] methods = clazz.getDeclaredMethods(); // 获取类中所有方法信息 返回值类型 方法名 参数类型 for(Method method : methods){ System.out.print(method.getReturnType().getSimpleName() + " " + method.getName()); Class[] pTypes = method.getParameterTypes(); System.out.print("("); for(Class t : pTypes){ System.out.print(t.getSimpleName()); } System.out.println(")"); } // 获取类中的某个指定方法 Method method = clazz.getDeclaredMethod("fun1", new Class[]{});// 没有参数,放入一个空数组就行 // 调用方法 BaseClass obj = new BaseClass(1, "张三", 2); // method.invoke(obj,null);//无参数可以写null或者new Object[]{} method.invoke(obj, new Object[]{}); // 获取有参数方法,并且调用 Method method2 = clazz.getDeclaredMethod("fun2", new Class[]{int.class}); System.out.println(method2.invoke(obj, new Object[]{3})); }
constructor类的相关方法
constructor.getParameterTypes(); 获得构造器参数类型
constructor.getModifiers(); 获得构造器修饰符信息
constructor.getName(); 构造器名称
clazz.getConstructor(new Class[]{...}); 获得指定构造器(根据类型)
BaseClass obj=(BaseClass) constructor.newInstance(new Object[]{....});//使用构造器创建对象
案例
public static void main(String[] args) throws Exception {
Class clazz=BaseClass.class;
Constructor[] constructors=clazz.getConstructors();
for(Constructor constructor:constructors){
Class[] types=constructor.getParameterTypes();
System.out.print(Modifier.toString(constructor.getModifiers()) +" "+constructor.getName());
System.out.print("(");
for(Class t:types){
System.out.print(t.getSimpleName()+" ");
}
System.out.println(")");
}
/获得指定的构造器
Constructor constructor=clazz.getConstructor(
new Class[]{int.class,String.class,double.class,double.class});
//用构造器创建对象
BaseClass obj=(BaseClass) constructor.newInstance(new Object[]{1,"张三",20,2});
System.out.println(obj.getName());
}
7、JavaBean拷贝
1)什么是JavaBean
一种Java类,重用的组件,符合一定设计规范的
2)符合规范如下
a、公共且完整的类
b、所有属性需要隐藏
c、提供公共的可访问私有属性的途径(getXXX,setXXX)
d、布尔类型的属性命名时把get/set换成is
e、一定要提供一个无参的构造器