您的位置:首页 > 其它

反射(概述,Class对象和信息,使用反射生产并操作对象,数组,反射与框架)

2015-07-23 15:03 239 查看
1.反射的概述

Java程序中有很多对象都会在运行时出现两种类型:编译时类型和运行时类型,例如代码Person() p = new Student(); 那么他编译时就是Person类,运行的时候就是Student类,我们可以instanceof来判断,但是对于一些不知道类型的类来说,我们就只能依靠该对象的类信息来判断了,这就叫反射。

2.获得Class对象和信息

获取类的对象,有三种方式:

示例:

public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种方法使用Class.forName()方法
Class<?> name = Class.forName("Demo1");

// 第二种方法 类名.class
Class className = Demo01.class;

// 第三种方法调用某个对象的 getClass()方法。
Demo01 d = new Demo01();
Class className1 = d.getClass();

}

}


从Class中获取信息

示例:

public class Demo02 {
public static void main(String[] args) throws NoSuchMethodException,
SecurityException {
Class fruit = Fruit.class;
// 获取构造器
Constructor[] constructors = fruit.getConstructors();
for (Constructor c : constructors) {
System.out.println("构造器:" + c.getName() + "--参数个数:"
+ c.getParameterCount());
}

Constructor c = fruit.getConstructor(String.class, String.class,
String.class);
System.out.println("2个参数的构造器是" + c.getName() + "修饰符:"
+ c.getModifiers());

// 获取方法:c.getParameterCount()表示的一般声明按声明顺序来声明的类型变量的数量
Method[] methods = fruit.getMethods();
for (Method m : methods) {
System.out.println("方法名是:" + m.getName() + "--参数个数是:"
+ c.getParameterCount());

}

Method[] declaredMethods = fruit.getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println("与访问权限无关的方法名是:" + m.getName() + "--参数个数是:"
+ c.getParameterCount());
}

Method method = fruit.getMethod("setShape", String.class);
System.out.println(method.getName() + " -- " + method.getModifiers());

// 获取成员变量
Field[] fields = fruit.getFields();
for (Field f : fields) {
System.out.println(f.getName() + " --" + f.getModifiers());
}

Field[] fields2 = fruit.getDeclaredFields();
for (Field f : fields2) {
System.out.println("与符号无关的字段:" + f.getName() + " --"
+ f.getModifiers());
}
}

}

class Fruit {
private String shape;
private String color;
public String length;

@Override
public String toString() {
return "Fruit [shape=" + shape + ", color=" + color + "]";
}

public String getShape() {
return shape;
}

public void setShape(String shape) {
this.shape = shape;
}

private String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

/*
* public String getLength() { return length; } public void setLength(String
* length) { this.length = length; }
*/
public Fruit(String shape, String color, String length) {
super();
this.shape = shape;
this.color = color;
this.length = length;
}

public Fruit() {
super();
}

}


运行结果:



3. 使用反射生产并操作对象

Class对象里面获得该类的方法(Method0), 构造器(Construtor)和成员变量(Field),程序可以通过对应的类来进行相应的操作。

1)使用反射创建对象

第一种:使用Class类的newInstance()方法来创建该类的实例。

第二种:通过Construtor对象的newInstance()方法来创建。

示例:

public class Demo03 {

/**
* @param args
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
//第一种使用Class类的newInstance()方法来创建该类的实例。
Fruit f1 = Fruit.class.newInstance();
f1.setColor("黄色");
f1.setShape("椭圆形");
f1.setLength("长");
System.out.println(f1);

//第二种通过Construtor对象的newInstance()方法来创建。
Class f = Fruit.class;
Constructor c = f.getConstructor(String.class, String.class,
String.class);
Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短");
System.out.println(obj);

}

}

class Fruit {
private String shape;
private String color;
public String length;

@Override
public String toString() {
return "Fruit [shape=" + shape + ", color=" + color + ",length="
+ length + "]";
}

public String getShape() {
return shape;
}

public void setShape(String shape) {
this.shape = shape;
}

private String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public String getLength() {
return length;
}

public void setLength(String length) {
this.length = length;
}

public Fruit(String shape, String color, String length) {
super();
this.shape = shape;
this.color = color;
this.length = length;
}

public Fruit() {
super();
}

}


运行结果:



2)使用反射调用方法

调用Method中包含的一个invoke(Object obj, Object ... args):该方法中的obj执行方法的主调,后面的args是执行该方法时传入的实参。

如果是private方法,可以将Method对象的accessible设置为true。 setAccessible()方法是Method的父类AccessibleObject.

示例:

public class Demo03 {

/**
* @param args
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Class f = Fruit.class;
Constructor c = f.getConstructor(String.class, String.class,
String.class);
Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短");
System.out.println(obj);
// 获取Method对象
Method m = f.getMethod("setShape", String.class);
// 操作方法
m.invoke(obj, "五角形");
System.out.println(obj);

// 获取Method对象
Method m2 = f.getDeclaredMethod("setLength", String.class);
m2.setAccessible(true);// 方法的访问控制符是private,需将Method对象的accessible设置为true
m2.invoke(obj, "长");
System.out.println(obj);

}

}

class Fruit {
private String shape;
private String color;
public String length;

@Override
public String toString() {
return "Fruit [shape=" + shape + ", color=" + color + ",length="
+ length + "]";
}

public String getShape() {
return shape;
}

public void setShape(String shape) {
this.shape = shape;
}

private String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public String getLength() {
return length;
}

private void setLength(String length) {
this.length = length;
}

public Fruit(String shape, String color, String length) {
super();
this.shape = shape;
this.color = color;
this.length = length;
}

public Fruit() {
super();
}

}


运行结果:



3)使用反射访问成员变量

首先反射的类应该符合JavaBean的原则,里面有set()和get()方法。

利用Field提供的getXxx(Obj obj)和setXxx(Obj obj, Xxx val)来获取obj的成员变量的值和设定成员变量的值

示例:

public static void main(String[] args) throws NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
Class f = Fruit.class;
Constructor c = f.getConstructor(String.class, String.class,
String.class);
Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短");
System.out.println(obj);
//获取成员变量:由于shape和color属性值都是私有的,需要设置accessible()
Field field = f.getDeclaredField("shape");
field.setAccessible(true);
String shape = (String) field.get(obj);
Field field2 = f.getDeclaredField("color");
field2.setAccessible(true);
String color = (String) field2.get(obj);
System.out.println(shape +"--" + color);

}

}

class Fruit {
private String shape;
private String color;
public String length;

@Override
public String toString() {
return "Fruit [shape=" + shape + ", color=" + color + ",length="
+ length + "]";
}

public String getShape() {
return shape;
}

public void setShape(String shape) {
this.shape = shape;
}

private String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public String getLength() {
return length;
}

private void setLength(String length) {
this.length = length;
}

public Fruit(String shape, String color, String length) {
super();
this.shape = shape;
this.color = color;
this.length = length;
}

public Fruit() {
super();
}

}


运行结果


</pre><p><span style="font-size:18px;">4)使用反射操作数组</span></p><p><span style="font-size:18px;">在java.lang.reflect包中的Array类,Array对象可以包含所有的数组。程序可以通过他来动态地创建数组,和操作数组元素。</span></p><p><span style="font-size:18px;">示例:</span></p><p><span style="font-size:18px;"></span></p><pre name="code" class="java">public class Demo04 {

/**
* @param args
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws InstantiationException,
IllegalAccessException {
Object obj = "abc";
print(obj);

int[] a = new int[] { 12, 4, 12, 44, 5, 4 };
print(a);

}

private static void print(Object obj) throws InstantiationException,
IllegalAccessException {

// 得到Class对象
Class<? extends Object> className = obj.getClass();
// 判断Class对象是否是数组
if (className.isArray()) {
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
System.out.println(Array.getInt(obj, i));
}
} else {
System.out.println(obj);
}

}

}


运行结果:



4.反射与框架

正如老师所说,框架就好像房屋的结构,他提供了门窗的接口,至于怎么样去装修就会对于不同的人有不同的风格。反射正是解决这样的问题,不同的人有不同的风格,当时安装的规则还是一样的,只是内容换了。

示例:

public class Demo05 {

/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws IOException,
ClassNotFoundException, InstantiationException,
IllegalAccessException {
InputStream is = new FileInputStream("E:/app2/Test/src/init.properties");
// 加载配置文件
Properties p = new Properties();
p.load(is);
String name = p.getProperty("name");
is.close();
// 反射再进行相关操作
Class<?> clazz = Class.forName(name);
ArrayList c = (ArrayList) clazz.newInstance();
c.add(1);
c.add(3);
c.add(5);
c.add(2);
for (int i = 0; i < c.size(); i++) {
System.out.print(c.get(i) + " ");
}

}

}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: