栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射机制详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射机制详解

上文中我们简略的讲解了一下反射机制的设计思想,本文我们详细讲解一下反射的具体实现

一.反射究竟实例化一个对象做了什么 1.1.分析主要做了JVM实例化对象中的哪个阶段

在之前文章中我们讲到jvm类的加载过程

加载-验证-准备-解析-初始化

所有的对象实例化都是依据第一步加载生成的class对象,反射也是依据class对象代码构建的对象,代码可以正常编译,那代码编译的验证也是通过了,准备阶段主要是对于静态变量的初始化,这一步JVM完成了,在解析阶段,已经将class对象中的静态引用改为静态变量的地址信息,所以反射主要做初始化的步骤操作

1.2.反射步骤

1.获取class方式 

 

方式备注
Class.forName(“完整类名带包名”)静态方法
对象.getClass()
任何类型.class

对象.getClass()

import  java.util.Date;
public class test {
    public static void main(String[] args) {
        Date date=new Date();
        System.out.println(date.getClass());
    }
}

类.class

import java.util.Date;
 
public class test {
    public static void main(String[] args) throws  Exception{
        System.out.println(Date.class);
 
    }
}
使用Class类提供的方法:public static Class forName(String className) throws ClassNotFoundException
import  java.lang.Class;
public class test {
    public static void main(String[] args) throws  Exception{
        Class date =Class.forName("java.util.Date");
        System.out.println(date);
 
    }
}

 通过反射实例化对象
以上事例中可以看出除了getClass()方法会实例化对象之外,其他的俩种不会产生实例化对象,所以取得Class类对象的一个最直接的好处就是通过反射实例化对象,该方法为:

对象.newInstance()

注:newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以。
否则会抛出java.lang.InstantiationException异常。

范例:

import  java.lang.Class;
import java.util.Date;
 
public class test {
    public static void main(String[] args) throws Exception{
        //通过反射机制,获取Class,通过Class来实例化对象
        Class  cl=Class.forName("java.util.Date");
        //newInstance() 这个方法会调用Date这个类的无参数构造方法,完成对象的创建。
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        Object object=cl.newInstance();
        System.out.println(object);
 
    }
}


5.反射主要使用的种类


5.1Class类方法:

 
举例常见的几种方法:

1.获取类名

public class demo {
    public static void main(String[] args) throws  Exception {
        Class cl=test.class;
        System.out.println(cl.getName());
        System.out.println(cl.getSimpleName());
    }
}


结果:

 

 2.获取类中的所有方法(重要)

public class getMethod {
    public static void main(String[] args) throws Exception {
        //通过反射机制,获取Class,通过Class来实例化对象
        Class cl = test.class;
        //通过getMethods方法获取所有public修饰的普通方法
        Method[] methods = cl.getMethods();
        for (Method i : methods) {
            System.out.println(i.getName());
        }
        System.out.println();
        //通过getDeclaredMethods返回类中所有的实例方法
        Method[] methods1 = cl.getDeclaredMethods();
        for (Method i : methods1) {
            System.out.println(i.getName());
        }
 
    }


5.2Field类方法

 

class Person{
        public String name;
        public   int age;
}
 
class Student extends Person
{
     public String school;
}
public class getField {
        public static void main(String[] args)  throws  Exception{
                Class cl= Student.class;1
 
                Field[] fields=cl.getFields();
                //返回public修饰的所有属性
                for (Field field:fields)
                {
                        System.out.println(field.getName());
                }
                System.out.println();
                //返回本类中的所有属性
                Field[] fie=cl.getDeclaredFields();
                for (Field field:fie)
                {
                        System.out.println(field.getName());
                }
                //通过反射操作属性-----set/get方法
                Object obj=cl.newInstance();
                Field getFid=cl.getDeclaredField("school");
                getFid.set(obj,"华润希望小学");
                System.out.println(getFid.get(obj));
 
        }
}


结果:

 

5.3:Method方法


重点getMethod()方法和invoke方法

范例:在有了反射机制处理之后,即使没有明确的Person类型对象(依然需要实例化对象,Object对象描述,所有 的普通方法必须在有实例化对象之后才可以进行调用)。就可以通过反射调用。通过反射去调用setter,getter方法

Method getMethod(String name,Class...parameterTypes)

name: method的名称

parameterTypes:method的参数类型的列表(参数顺序需按声明method时的参数列表排列)

返回:符合method名称和参数的method对象

抛出错误:NoSuchMethodException (没有找到所要查询的Method对象或Method名称为“”或“”) NullPointerException (所要查询的Method对象的名称为null) SecurityException(调用的类或其父类没有调用权限)

invoke方法:

作用:调用包装在当前Method对象中的方法。

原型:Object invoke(Object obj,Object...args) 参数解释:obj:实例化后的对象                args:用于方法调用的参数

返回:根据obj和args调用的方法的返回值

抛出错误:IllegalAccessException(Method对象强制Java语言执行控制或无权访问obj对象) IllegalArgumentException(方法是实例化方法,而指定需要调用的对象并不是实例化后的类或接口)
import java.lang.reflect.Method;
class Person
{
    private  String name;
    private  int age;
    private  String sex;
 
    public int getAge() {
        return age;
    }
 
    public String getName() {
        return name;
    }
 
    public String getSex() {
        return sex;
    }
    public void setAge(int age) {
        this.age = age;
    }
 
    public void setSex(String sex) {
        this.sex = sex;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}
 
public class getMethod {
    public static void main(String[] args) throws Exception {
        //通过类名.class获取class对象
        Class cl=Person.class;
        //实例划对象
        Object o=cl.newInstance();
        //通过getMethon方法取得setName这个方法的实例化对象,方法名称与参数类型
        Method setMethod=cl.getMethod("setName", String.class);
        //通过invoke调用方法
        setMethod.invoke(o,"wangyang");
        Method  getMethod=cl.getMethod("getName");
        Object result=getMethod.invoke(o);
        System.out.println(result);
    }
 
}


此类操作的好处是:不再局限于某一具体类型的对象,而是可以通过Object类型进行所有类的方法调用。这个操作 必须掌握.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/999591.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号