Java反射机制

目录

反射

反射API

CLass类

全限定类名说明

Class类四种创建方式

简单使用并解释其他API

注解+反射(简单应用实例)


反射

        Java反射体现出了Java的动态性,就是在Java运行期间直接对任意对象进行操作,比如属性、方法。反射概念是非常抽象的^o^,假设我们做一件事都有一个计划我们就按照计划行事(这相当于我们写的代码一行一行执行下去),当遇见特殊情况之前计划不能实施了我们就需要见机行事灵活实施(这里灵活变通就是反射,就是动态的把事情处理了),通过下面反射API的代码可以进一步了解反射。为了体现反射动态性简单看一段代码,以下代码就是动态创建一个对象。

/**
每次调用此方法输入一个全限定类名就会帮我们
创建一个新的对象,这就能体现出反射动态性,
这里体现动态创建对象
*/
public class ReflectDemo {
     static Object getInstance(String path) throws Exception {
         Class<?> clas = Class.forName(path);
         Object obj = clas.newInstance();
         return obj;
     }
    public static void main(String[] args) throws Exception {
       Scanner scanner=new Scanner(System.in);
       while (true){
           String next = scanner.next();
           if("exit".equals(next))
               break;
           System.out.println(getInstance(next));
       }
    }

}

反射API

        在Java.lang.reflect有很多反射API,来实现Java反射机制。

         java.lang.Class

        java.lang.reflect.Method : 类的方法

        java.lang.reflect.Constructor : 类的构造方法

        java.lang.reflect.Field: 成员变量

        ..........................

CLass类

        Class的实例就对应着一个运行时类,类加载到内存在运行期间就会有其CLass与之相对应,这个CLass实例就会记录加载类的相关信息,并且每一个被加载的类都有一个(有且仅有一个)与其对应的Class实例。增加理解:javac.exe 会生成字节码文件(.calss)。java.exe就会将字节码文件加载到内存中这称为类加载的过程,加载到内存中的类我们称为运行时类,运行时类就作为Class的实列。

全限定类名说明

        为下面不重复说明全限定类名,这里做个解释,就是包名点类名(包名.类名)列如String类在package java.lang;中类名为String,全限定类名为:java.lang.String。

Class类四种创建方式

        下面三种创建方式最为常见

 //直接点class
 Class clazz= Person.class;
//通过Object中方法返回
 Person person=new Person();
 Class clas=person.getClass();
/**Class类中的静态方法。
   使用全限定类名,重点掌握
   相对上面两个而言此种方式更能体
   现动态性,如一开始的列子
*/
 Class aclazz =Class.forName("com.Person");

        最后一种

//类加载器方式,这个作为了解
ClassLoader classLoader = People.class.getClassLoader();
Class<?> aClass = classLoader.loadClass("com.Person");

简单使用并解释其他API

public class ReflectTest extends Object{
    public static void main(String[] args) throws Exception  {
     Class clazz= Class.forName("com.Person");//获取Person类实例
     Person p=(Person) clazz.newInstance();//生成对象,相当于调用了无参构造方法
        Method[] methods = clazz.getDeclaredMethods();//获取当前类里面的所有方法
        for (Method method : methods) {//遍历
            System.out.println(method);
        }
      System.out.println("/********************************/");
     Method[] methods1 = clazz.getMethods();//获取当前类及其父类用Public修饰的方法
        for (Method method : methods1) {
            System.out.println(method);
        }
     System.out.println("/********************************/");
        Method sayHi = clazz.getMethod("sayHi");//获取当前类名类的方法Public修饰的
        sayHi.invoke(p);
        System.out.println("/********************************/");
        //获取名称的方法
        Method sayHello = clazz.getDeclaredMethod("sayHello",String.class);
        sayHello.invoke(p,"皮卡丘");
        System.out.println("/********************************/");
   //获取在此类中该名称的方法
        Method method=clazz.getDeclaredMethod("say",String.class);
//因为它是private修饰的需要打开可访问
        method.setAccessible(true);
        method.invoke(p,"阿宝");
//建议关闭,防止他人访问
        //method.setAccessible(false);
    }

}
public class Person {
    public String name="张三";
    private int age=20;
    public Person(){}
    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void sayHi(){
        System.out.println(name+"说:hello!");
    }
    public void sayHello(String info){
        System.out.println(info+"说:hi!");
    }
    private void say(String d){
        System.out.println(d+"说:hello!");
    }
}

public void com.Person.sayHi()
public void com.Person.sayHello(java.lang.String)
private void com.Person.say(java.lang.String)
/********************************/
public void com.Person.sayHi()
public void com.Person.sayHello(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
/********************************/
张三说:hello!
/********************************/
皮卡丘说:hi!
/********************************/
阿宝说:hello!

         记住几个关键地方getDeclaredXXXs()获取当前类无论用啥权限修饰符都能获取。getXXXs()获取当前类及其父类并且有public修饰的。getDeclaredXXX(String name,parameterType....)name指获取假设xxx为Method对应获取方法,,parameterType参数对应类型的运行时类,可参考我上面代码,getxxx(String name,parameterType....)只获取public修饰的。如果要运行private修饰的要设置可访问的xxx.setAccessible(true);

xxx有:Method(方法),Annotation(注解),Constructor(构造器),Fieldde(成员变量)等

注解+反射(简单应用实例)

public class BeanTest {
    public static void main(String[] args) throws Exception{
        String pakege= BeanTest.class.getPackage().getName();
/*加载到类路径只获取.class文件
*/
      File file=new File(BeanTest.class.getResource(".").toURI());
        File[] files = file.listFiles((f) -> f.getName().endsWith(".class"));
        for (File file1 : files) {
            String fileName=file1.getName();
            String sub=fileName.substring(0,fileName.indexOf("."));
//通过拼接得到全限定类名
            fileName=pakege+"."+sub;
            //System.out.println(fileName);
            Class clazz = Class.forName(fileName);
/**类上有自定义注解MyComponent
创建出对象,无参构造方法
所有我在每个类中构造器都输出一句话验证
只有类上有注解我们才创建类
*/
            if(clazz.isAnnotationPresent(MyComponent.class)){
                Object obj = clazz.newInstance();
            }
        }
    }
}
/**
自定义注解在上节,我已经介绍过不清楚的可以看看,这里就不
一一阐述
**/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
    String value() ;
}
//控制台结果
我类上有注解哦^_^,我是MyBean
@MyComponent("myBean")
public class MyBean {
  public MyBean(){
      System.out.println("我类上有注解哦^_^,我是MyBean");
  }
}

public class MyBean1 {
    public class MyBean {
        public MyBean(){
            System.out.println("我类上有没注解-_-,我是MyBean1");
        }
    }
}

           通过此案列注解加反射原理让我们更加的清楚知道两种在一起使用能解决很多问题,框架就是注解+反射+设计模式。基础的学习有利于我们去看框架的底层实现原理,可以更深层次了解框架。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值