JAVA进阶(反射机制)


一、反射机制是什么?

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));//取得属性内容
    }
}

在这里插入图片描述


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值