反射与内省
什么是反射
java反射机制是在运行状态中,对任意类都能知道它的所有属性和方法,对于任意对象都能调用它的任意方法,这种动态获取信息以及动态调用对象的方法的功能就称为java语言的反射机制。
Class类的作用
Class类是java反射机制的起源和入口,用于获取与类相关的各种信息,提供了获取类信息的相关方法。Class类继承与Object。
Class类是所有类的图纸。每个类都有自己的对象,就好比图纸和实物的关系;每个类也可以看做一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应的方法取出相应的信息。比如:类的名字、属性、方法、构造方法、父类和接口。
Class类实例化的三种方式(常用的)
1. 通过对象. getClass ( ) 实例化
Person p = new Person ( ) ;
Class clazz = p. getClass ( ) ;
2. 通过类名. Class实例化
Class clazz = p. Class;
3. 通过调用Class类的forName ( ) 方法获取
Class. forName ( "全类名" ) ;
通过Class取得类的完整信息和调用类中的属性和方法
Class. newInstance ( ) ;
Class. getFields ( ) ;
Class. getMethods ( ) ;
Class. getDeclaredFields ( ) ;
Class. getDeclaredMethods ( ) ;
例子:
public class Person {
private String name;
private int age;
public int sex;
public int height;
public Person ( ) {
}
public Person ( String name, int age) {
this . name = name;
this . age = age;
}
private void print ( ) {
System. out. println ( "name" + name) ;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public int getAge ( ) {
return age;
}
public void setAge ( int age) {
this . age = age;
}
public void say ( String name) {
System. out. println ( name+ "fanlenile" ) ;
}
@Override
public String toString ( ) {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", height=" + height +
'}' ;
}
}
-- -
import java. lang. reflect. Field;
import java. lang. reflect. Method;
import java. lang. reflect. Modifier;
public class ReflectTest2 {
public static void main ( String[ ] args) {
Person person = new Person ( "小花花" , 22 ) ;
Class clazz = person. getClass ( ) ;
Field[ ] fields = clazz. getFields ( ) ;
for ( Field field : fields) {
System. out. print ( field. getName ( ) + " " ) ;
System. out. println ( field. getModifiers ( ) ) ;
System. out. println ( Modifier. toString ( field. getModifiers ( ) ) ) ;
}
System. out. println ( "---------------" ) ;
Method[ ] methods = clazz. getMethods ( ) ;
for ( Method method : methods) {
System. out. print ( method. getName ( ) + " " ) ;
System. out. println ( method. getModifiers ( ) ) ;
System. out. println ( Modifier. toString ( method. getModifiers ( ) ) ) ;
System. out. println ( "---------------------------" ) ;
}
Field[ ] declaredFields = clazz. getDeclaredFields ( ) ;
for ( Field declaredField : declaredFields) {
System. out. println ( declaredField. getName ( ) ) ;
}
System. out. println ( "---------------------" ) ;
Method[ ] declaredMethods = clazz. getDeclaredMethods ( ) ;
for ( Method declaredMethod : declaredMethods) {
System. out. println ( declaredMethod. getName ( ) ) ;
}
try {
Method print = clazz. getDeclaredMethod ( "print" ) ;
print. setAccessible ( true ) ;
print. invoke ( person) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
try {
Method getName = clazz. getDeclaredMethod ( "say" , String. class ) ;
getName. invoke ( person, "白白" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
}
九大预定义的Class对象:
八大基本数据类型和void
JavaBean的概念
什么是JavaBean?
Bean能够理解为组件的意思,JavaBean就是java组价,在广泛的理解里就是一个类。对于组件来说,关键在于具有“能够被IDE构件工具侦测其属性和事件”的能力,通常在Java中:
一个JavaBean要具备这样的命名规则:
1. 对于一个名称为XXX的属性,通常你要写两个方法getXxx ( ) 和setXxx ( ) 。任何浏览这些方法的工具,都会把get和set的最后面一个 字母自动转换为大写。
2. 对于布尔型属性,可以使用以上get和set的方法,不过也可以把get替换成is
3. Bean的普通方法不必遵循以上的命名规则,不过他们必须是public 的
内省
内省是java语言对Bean类属性、事件的一中缺省处理方法。例如类A中有属性name, 那我们可以通过getName ( ) 、setName ( ) 来得到值或者设置新的值。
通过getName ( ) / setName来访问name属性,这就是默认的规则。
Java中提供了一套API用来访问某个属性的getter/ setter方法,这些API存放在java. beans包中,一般的做法是通过类Introspector的getBeanInfo方法来获取某个对象的beaninfo信息,然后通过BeanInfo来获取属性的描述器( PropertyDescriptor) , 通过这个属性描述器就可以获取到某个属性的getter和setter方法,然后我们就可以通过反射机制来调用这些方法。
Introspector相关API
1. Introspector类: 提供getBeanInfo ( Class) 方法
2. BeanInfo类:该类实现此BeanInfo接口并提供有关其Bean的方法、属性、事件等显示信息。该类提供getMethodDescriptors ( ) getPropertyDescriptors ( ) 方法,分别用来获取类中的方法、属性。
3. PropertyDescriptor类:描述JavaBean通过一对存储器方法导出了一个属性。getReadMethod ( ) :获得应该用于读取属性值的方法。getWriteMethod ( ) 获得应该用于写入属性值的方法。
4. MethodDescriptor类:描述一种特殊方法,即JavaBean支持从其他组件对其进行外部访问。getMethod ( ) :获得此MethodDescriptors封装的方法。
内省例子
配置文件:
name= introspectordemo. Cat
cat. id= 20
cat. name= 波斯猫
cat. price= 2000.0f
-- Cat类
public class Cat {
private int id;
private String name;
private float price;
public Cat ( ) {
}
public int getId ( ) {
return id;
}
public void setId ( int id) {
this . id = id;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public float getPrice ( ) {
return price;
}
public void setPrice ( float price) {
this . price = price;
}
@Override
public String toString ( ) {
return "Cat{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
'}' ;
}
}
-- - CatFactory类
import java. beans. *;
import java. io. IOException;
import java. lang. reflect. Method;
import java. util. Properties;
public class CatFactory {
private static Properties properties;
static {
properties = new Properties ( ) ;
try {
properties. load ( Thread. currentThread ( ) . getContextClassLoader ( ) . getResourceAsStream ( "introspectordemo/bean.properties" ) ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public static Cat getCat ( String name) {
Cat cat = null;
if ( name == "cat" ) {
String cname = properties. getProperty ( "name" ) ;
try {
Class aClass = Class. forName ( cname) ;
cat = ( Cat) aClass. newInstance ( ) ;
BeanInfo beanInfo = Introspector. getBeanInfo ( aClass) ;
PropertyDescriptor[ ] propertyDescriptors = beanInfo. getPropertyDescriptors ( ) ;
for ( PropertyDescriptor propertyDescriptor : propertyDescriptors) {
System. out. println ( propertyDescriptor. getName ( ) ) ;
if ( "name" . equals ( propertyDescriptor. getName ( ) ) ) {
Method writeMethod = propertyDescriptor. getWriteMethod ( ) ;
writeMethod. invoke ( cat, properties. getProperty ( "cat.name" ) ) ;
} else if ( "id" . equals ( propertyDescriptor. getName ( ) ) ) {
Method writeMethod = propertyDescriptor. getWriteMethod ( ) ;
writeMethod. invoke ( cat, Integer. parseInt ( properties. getProperty ( "cat.id" ) ) ) ;
} else if ( "price" . equals ( propertyDescriptor. getName ( ) ) ) {
Method writeMethod = propertyDescriptor. getWriteMethod ( ) ;
writeMethod. invoke ( cat, Float. parseFloat ( properties. getProperty ( "cat.price" ) ) ) ;
}
}
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
return cat;
}
}
-- - Test测试类
public class Test {
public static void main ( String[ ] args) {
String name = "cat" ;
Cat cat = CatFactory. getCat ( name) ;
System. out. println ( cat) ;
}
}