一、反射机制是什么?
java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制
二、反射调用
1.Class类
- java.util.Class是一个类,这个类是反射操作的源头,所有的反射都要此类开始进行
- Class类对象实例化三种实例化方式:
- 1.调用object类中的getClass()方法
- 2.使用 类.class
- 3.调用Class类提供的forName(String className)方法
package 反射机制;
import java.util.Date;
public class ReflectDemo2 {
public static void main(String[] args) throws Exception{
Date date = new Date();
Class<?> cla = date.getClass();
Class<?> cla1 = Date.class;
Class<?> cla2 = Class.forName("java.util.Date");
System.out.println("调用---getClass方法输出(需要产生Date类的对象): "+cla);//获取了完整的类名
System.out.println("调用---类.class方法输出(不需要产生Date类的对象): "+cla1);
System.out.println("调用---Class.forName()方法输出(不需要import java.util.Date): "+cla2);
}
}
2.反射实例化对象
- 对象实例化不一定使用关键字new
- new 是造成耦合的最大元凶,反射解耦合
- 反射实例化对象,不使用关键字new,实例化对象方法:public T newInstance()
package 反射机制;
class Book
{
public Book()
{
System.out.println("Book类的无参构造!!!");
}
@Override
public String toString() {
return "这是一本书";
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception{
Class<?> cla = Class.forName("反射机制.Book");
Object obj = cla.newInstance();
//相当于使用new关键字调用无参构造实例化,使用object类接收因为泛型的类型不确定,
//是否可以理解为间接的使用一个对象实例化另一个对象
System.out.println(obj);
}
}
package 反射机制;
interface Fruit
{
void eat();
}
class Apple implements Fruit
{
@Override
public void eat() {
System.out.println("我要吃苹果!");
}
}
class Orange implements Fruit
{
@Override
public void eat() {
System.out.println("我要吃橙子!");
}
}
class Factory {
public static Fruit getInstance(String classname) {
// if ("Apple".equals(classname)) return new Apple();
// else if ("Orange".equals(classname)) return new Orange();
// else return null;
Fruit f = null;
try {
f = (Fruit)Class.forName(classname).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return f;
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception{
Fruit f = Factory.getInstance("反射机制.Orange");
f.eat();
}
}
- 每增加一个类。都要修改工厂类,因为工厂中的类都是通过new关键字返回实例化对象,通过反射实例化对象,可以不用修改Factory类,直接修改getInstance()中的参数即可,降低类之间的耦合度!!!
3.反射调用构造方法
package 反射机制;
import java.lang.reflect.Constructor;
class Person
{
private String name;
private int age;
public Person(String name,int age)
{
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+" 年龄:"+this.age;
}
}
public class ReflectDemo2 {
public static void main(String[] args) throws Exception{
Class cla = Class.forName("反射机制.Person");
Constructor<?> con = cla.getConstructor(String.class,int.class);//获取构造方法对象,参数类型对应构造方法中的参数类型
Object obj = con.newInstance("huicoker",21);//相当于调用有参构造实例化对象
System.out.println(obj);
}
}
4.反射调用普通方法
package 反射机制;
import java.lang.reflect.Method;
class Animal
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ReflectDemo3 {
public static void main(String[] args) throws Exception{
Class<?> cla = Class.forName("反射机制.Animal");
Object obj = cla.newInstance();
String fieldname = "name";//要操作的成员
Method setMet = cla.getMethod("set"+init(fieldname),String.class);//取得指定方法对象(方法名称,方法中参数类型),方法中没有参数类型可不写
Method getMet = cla.getMethod("get"+init(fieldname));//取得指定方法对象
setMet.invoke(obj,"Hello Kitty");//等价于animal类对象.setName("Hello Kitty")
System.out.println(getMet.invoke(obj));//利用取得的方法对象调用普通方法
//反射隐藏了类,利用反射可以对任意类的指定方法进行调用,实现了保护机制
}
//此类的作用是把操作成员“name”的首字母大写,与set或get合并为具体的方法名称setName,getName
public static String init(String str)
{
return str.substring(0,1).toUpperCase()+str.substring(1);
}
}
5.反射调用私有成员
package 反射机制;
import java.lang.reflect.Field;
//反射调用成员
class Car
{
private String name;
}
public class ReflectDemo4 {
public static void main(String[] args) throws Exception{
Class<?> cla = Class.forName("反射机制.Car");
Object obj = cla.newInstance();
Field nameField = cla.getDeclaredField("name");//取得指定成员对象
nameField.setAccessible(true);//取消封装,让private不起作用
nameField.set(obj,"劳斯莱斯");//设置属性内容:
System.out.println(nameField.get(obj));//取得属性内容
}
}