java反射 一些理解

JAVA反射机制

什么是反射:

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
  对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
 
    条件:
 
  JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,
用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、
或唤起其methods。(百度百科)
  尽管java不是动态语言 但是java提供了一个非常重要的API用于完成反射的需求。Reflection
  学习:
  要学习反射,先来介绍下需要学习或者理解的类(直接抄的API的解释词语) 其实能熟练读懂api比看一些教程有用的多
 
  1、java.lang.Class<T>//Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
 
  2、java.lang.reflect(包)
  java.lang.reflect.Constructor<T> //提供关于类的单个构造方法的信息以及对它的访问权限。
  java.lang.reflect.Field //Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
  java.lang.reflect.Method //Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
  java.lang.reflect.Modifier  //Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
 
  例子:
  获取包名,类名.......
    
public static void main(String[] args) {
        String strObj= new String();//创建对象,这种方式创建,比较容易理解创建了一个String对象
        Class classObj = strObj.getClass();//获取了一个运行中的实例模型  有兴趣的可以去读一下源码,就不往外贴了
        System.out.println(classObj.getName());//完整类名
    System.out.println(classObj.getPackage().getName());//包名
//Result java.lang.String  java.lang

}

  实例化Class对象的方式:通常理解实例化一个类的Class模型,比如我使用的String这个类,就是实例化了一个String的Class的模型对象

    public static void main(String[] args) throws Exception {
        Class<?> classObj = null;
        classObj = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        System.out.println(classObj.getName());
        classObj=new String().getClass();
        System.out.println(classObj.getName());
        classObj=String.class;
        System.out.println(classObj.getName());
        //Result  java.lang.String  java.lang.String  java.lang.String
    }
  获取父类和接口
    public static void main(String[] args) throws Exception {
        Class<?> classObj = null;
        classObj = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        System.out.println(classObj.getSuperclass().getName());//父类名
        Class[] classList=classObj.getInterfaces();//接口列表
        for (Class obj: classList) {
            System.out.println(obj.getName());//实现的接口
        }
        //Result  java.lang.Object  默认所有的类都是继承Object类
        // java.io.Serializable 
        // java.lang.Comparable 
        // java.lang.CharSequence
    }


上方这些在Class的API都有详细介绍

通过反射实例化一个类的对象:
两种方式使用类的默认构造方法,指定一个构造方法
public class Test {


    public static void main(String[] args) throws Exception {
        //----------------------------------
        //第一种
        Class<?> classObj = null;
        classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        Student student = (Student) classObj.newInstance();
        student.setName("明");
        System.out.println(student.toString());
        //第二种
        Constructor<?> cons[] = classObj.getConstructors();//获取所有的构造方法
        for (Constructor constructor: cons) {
            Class<?> [] params=  constructor.getParameterTypes();
            for (Class param : params) {
                System.out.println(param.getName());
            }
            System.out.println("****************************");//打印几次说明有几个构造方法啊
        }
        Student student1 = (Student) cons[1].newInstance("marry",10);
        System.out.println(student1.toString());
    }




}
class Student{
    private String name;
    private Integer age;

    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

控制台:

  
  //Result  
  Student{name='明', age=null}
  ****************************
  java.lang.String
  java.lang.Integer
  ****************************
  Student{name='marry', age=10}



 

获取类的全部属性

 public static void main(String[] args) throws Exception {
        //----------------------------------
        //第一种
        Class<?> classObj = null;
        classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        Field[]  fields=  classObj.getDeclaredFields();
        for (Field field: fields) {
                    //修饰符  + 类型  + 名字
            System.out.println(Modifier.toString(field.getModifiers()) +"  "+field.getType().getSimpleName()+"    "+field.getName());
        }
    }

//console

修改类的属性无视private
public static void main(String[] args) throws Exception {
        //----------------------------------
        //第一种
        Class<?> classObj = null;
        classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)

        Object object=classObj.newInstance();

        Field field = classObj.getDeclaredField("name");// 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
        field.setAccessible(true);
        field.set(object, "xiaomei");
        System.out.println(field.get(object));// field.get(Object obj) 反回指定对象上此 Field 表示的字段的值。
    }
//console

 获取类的全部方法

  先给上面的Student类增加一个方法

 public void doHomeWork(){
        System.out.println(this.name+"开始写作业了!");
    }
public void doHomeWork() {
System.out.println("开始写作业了!");
}
 

 

public static void main(String[] args) throws Exception {
        //----------------------------------
        //第一种
        Class<?> classObj = null;
        classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        Method[] methods = classObj.getDeclaredMethods();
        for (Method method : methods) {

            System.out.println( Modifier.toString(method.getModifiers())+"  "//修饰符
                    +method.getGenericReturnType().toString()+"  "+//返回值 
                    method.getName())
            ;//方法名
        }
        //public  class java.lang.String  toString
       //  public  class java.lang.String  getName
        //public  void  setName
       // public  class java.lang.Integer  getAge
       // public  void  setAge
        //public  void  doHomeWork
}

  直接调用类的方法:

    public static void main(String[] args) throws Exception {
        Class<?> classObj = null;
        classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API)
        Method methods = classObj.getMethod("doHomeWork");
        methods.invoke(classObj.newInstance());
        //控制台   null开始写作业了!

        Method methods1 = classObj.getMethod("doHomeWork",String.class);
        methods1.invoke(classObj.newInstance(),"\"小明\"");
     //控制台 小明开始写作业了! }

 

 写了这些反射在java中怎么使用和基本用法,总得做点什么,下一篇反射在代理模式中的应用----------->>>

  
posted @ 2017-07-21 11:58  LewsKay  阅读(326)  评论(1编辑  收藏  举报