- 动态语言 javascript是动态语言
- 静态语言(非动态语言)java
- 例如:创建一个对象,是否可以在运行时给对象增加属性和方法,java不具有这种特性,对象创建完成后不能增加属性和方法,但是可以通过反射机制实现动态语言的部分特性
- java中先有类,然后再有对象,类在创建对象的时候只加载一次(方法区)
- 反射指的是,在程序运行时分析类的结构的能力
- 反射中常见的类(接口)
- Class:代表类对象,它是使用反射的入口,可以通过反射获得当前类的属性,方法,父类和实现的接口等
- Class是一个类型,它的实例有String.class,Double.class,Dog.class;
- String 的实例:"hello word"
- 例如:
- Dog d=new Dog();//将类的结构加载到java虚拟机,然后在堆里创建类对象,一个类只加载一次
- Class即是当前类的结构(该类相当于模版),将模版加载到jvm,以后创建类对象都先往jvm中查找是否已存在该类的模版
- JDK API1.6关于Class的说明:
-
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注解是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class
对象。基本的 Java 类型(boolean
、byte
、char
、short
、int
、long
、float
和double
)和关键字void
也表示为Class
对象。Class
没有公共构造方法。Class
对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass
方法自动构造的。
-
- 获得类对象的方法(Class的实例),三种
- Class c=String.class;(String的类对象,存储的String类的元数据)
- Class c=Class.forName(完整的类名);
- Class c=对象.getClass();
- 例如:
Class<?> c=String.class;//获得String的类对象 Class c1=d.getClass();//获得Dog的类对象 Class c2=Class.forName("com.oracle.test.Dog");
- Class常用的方法
- String getName();//获得当前类的类名
输出结果为:System.out.println(c.getName()); System.out.println(c1.getName()); System.out.println(c2.getName());
//结果为当前类的全称,包括包名java.lang.String com.oracle.test.Dog com.oracle.test.Dog
- String getSimpleName();//只获得当前类的名称,不含包名
输出结果:System.out.println(c.getSimpleName());
String
- Class<?> getSuperClass();//获得当前类的父类
System.out.println(d.getClass().getSuperclass()); 结果: class com.oracle.test.Animal
- Class<?>[] getInterfaces();//获得当前类的实现接口类对象或者接口实现的接口,返回值为Class数组
- 在进行不同类的比较的时候可以直接使用==判断
public static void equals(Object o1,Object o2){ if(o1.getClass()==o2.getClass()) { System.out.println("类型相同,都是"+o1.getClass()); }else { System.out.println("类型不同一个是"+o1.getClass()+"另一个是"+o2.getClass()); } }
- Field类:
Field
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 (JDK API 1.6)- 即Field代表类的属性;例如:private int age;(访问修饰符,数据类型,属性名)
- 获得Field的方法有四种,都是Class类中的方法
- Field :getField(String name);获得指定名称的公共属性(反映此
Class
对象所表示的类或接口的指定公共成员字段) - Field[] :getFields();获得所有公共的属性(所有可访问公共字段。)
- Field :getField(String name);获得指定名称的公共属性(反映此
-
- 测试结果:
- //注意属性为访问修饰符,包名,属性名,可以通过getName()方法只获得属性名
Student st=new Student(); Dog d=new Dog(); System.out.println(d.getClass().getField("name")); getField(st); public static java.lang.String com.oracle.test.Animal.name Student属性有: public java.lang.String com.oracle.vo.Student.sex public java.lang.String com.oracle.vo.Student.type
- Field getDeclaredField(String name);获得当前类中定义的某个属性
- Field[] getDeclaredFields();获得当前类的所有属性(不包括继承的属性)
/** * 获得当前类的所有属性 * @param obj */ public static void getDeclaredField(Object obj) { Field[] fd=obj.getClass().getDeclaredFields();//获得当前类的所有属性 System.out.println(obj.getClass().getSimpleName()+"属性有:"); for (Field f : fd) { System.out.println(f); } }
测试结果getDeclaredField(st); System.out.println("======================="); getDeclaredField(d);
Student属性有: private int com.oracle.vo.Student.stuid private java.lang.String com.oracle.vo.Student.name public java.lang.String com.oracle.vo.Student.sex public java.lang.String com.oracle.vo.Student.type ======================= Dog属性有: public java.lang.String com.oracle.test.Dog.s public java.lang.String com.oracle.test.Dog.w
- Field 的用法
- String getName();获得属性名称
- Class getType();获得属性类型
- int getModifiers(); 返回此类或接口以整数编码的 Java 语言修饰符
Field[] fd=obj.getClass().getFields();//获得所有的公共属性 System.out.println(obj.getClass().getSimpleName()+"属性有:"); for (Field f : fd) { System.out.println(f.getModifiers()+" "+f.getType().getSimpleName()+" "+f.getName()); }
Student属性有: 1 String sex 1 String type
- 关于modifiers的说明
/** * The {@code int} value representing the {@code public} * modifier. */ public static final int PUBLIC = 0x00000001; /** * The {@code int} value representing the {@code private} * modifier. */ public static final int PRIVATE = 0x00000002; /** * The {@code int} value representing the {@code protected} * modifier. */ public static final int PROTECTED = 0x00000004; /** * The {@code int} value representing the {@code static} * modifier. */ public static final int STATIC = 0x00000008; /** * The {@code int} value representing the {@code final} * modifier. */ public static final int FINAL = 0x00000010; /** * The {@code int} value representing the {@code synchronized} * modifier. */ public static final int SYNCHRONIZED = 0x00000020; /** * The {@code int} value representing the {@code volatile} * modifier. */ public static final int VOLATILE = 0x00000040; /** * The {@code int} value representing the {@code transient} * modifier. */ public static final int TRANSIENT = 0x00000080; /** * The {@code int} value representing the {@code native} * modifier. */ public static final int NATIVE = 0x00000100; /** * The {@code int} value representing the {@code interface} * modifier. */ public static final int INTERFACE = 0x00000200; /** * The {@code int} value representing the {@code abstract} * modifier. */ public static final int ABSTRACT = 0x00000400; /** * The {@code int} value representing the {@code strictfp} * modifier. */ public static final int STRICT = 0x00000800;
- 例如:
调用getModifiers()方法得到结果为public class Student { public int stuid; private String name; public static String sex; protected String type; Date bitrh; private static final int M=10; }
Student属性有: 1 int stuid 2 String name 9 String sex 4 String type 0 Date bitrh 26 int M
根据JDK源码可知,访问修饰符是采用十六进制存储的整型常量
- 对应的十进制即为:
- PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048
- PUBLIC: 1
- 9=8+1即为public static
- 26=16+8+2即为private static final
- 关于Modifier的说明
-
表示程序元素(如类、方法或字段)上的修饰符。
并非所有修饰符都适用于所有种类的元素。当两个或多个修饰符出现在某一元素的源代码中时,那么按照惯例(尽管没有要求),它们出现的顺序与上述内容中列出常量的顺序相同。(基本按照从小到大的顺序出现)
-
常用的方法
-
Stirng : toString();返回此修饰符的小写名称。(将getModifiers()方法获得的常量转换成对应的访问修饰符)
-
static Modifier
valueOf(); 返回带有指定名称的该类型的枚举常量。 -
static Modifier[] values();返回该类的所有的枚举常量
-
- 使用反射机制生成sql语句
- 例如生成插入语句
public static void save(Object obj) { //得到参数对应的类的所有属性字段 Field[] f=obj.getClass().getDeclaredFields(); StringBuffer sb1=new StringBuffer();//sql语句的前半部分 StringBuffer sb2=new StringBuffer();//sql语句的后半部分 sb1.append("insert into ").append(obj.getClass().getSimpleName()+" ("); sb2.append(" values("); for(int i=0;i<f.length;i++) { if(i<f.length-1) { sb1.append(f[i].getName()+","); sb2.append("?,"); }else { sb1.append(f[i].getName()+")"); sb2.append("?)"); } } System.out.println(sb1.append(sb2).toString()); }
执行结果:insert into Student (stuid,name,sex,type,bitrh,M) values(?,?,?,?,?,?)