java-关于反射使用

关于java.lang.Class类的理解

1.类的加载过程:

程序经过javac.exe的命令之后,会生成一个或多个字节码文件(.class)文件。
接着我么使用java.exe命令对某个字节码文件进行解释运行,相当于某个字节码文件加载到内存中,此过程就叫做类的加载。此过程钟就称为类的加载,加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class类的实例。
//万事万物全部为对象

2.换句话说,Class的实例就对应着一个运行时类
3.加载到内存钟的运行时类,会缓存一定的时间,在此时间之内,我门可以通过不同的方式来获取这个运行时类

获取Class实例的方式

public void test3(){
    //方式一:调用运行类的属性.class
    Class clazz1 = Persion.class;
    System.out.println(clazz1);
    //方式二:通过运行时类的对象
    Persion p1 = new Persion();
    Class clazz2 = p1.getClass();
    System.out.println(clazz2);
    //方式三:掉哟Class的静态方法:forName(String calssPath)
    Class clazz3 = Class forName("package.Persion")
    System.out.println(clazz3);
    //使用类的加载器:Classloader
    ClassLoader classloader = 当前主包.class.getClassLoader();
}

一个类就会创建一个大的Class类

了解ClassLoader(加载器,将自定义的类或者系统的类加载到内存中的加载类)
public calss ClassLoaderTest{
    @Test
    public void test1(){
		//对于自定义的类,使用的是系统加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);
        //加载类的.getParent();获取的是扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);
        //调用扩展类加载器的.getParent()无法获取引导类加载器
        //引导类加载器主要负责的是加载java核心类库,无法加载自定类
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);
        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println(classLoader3);

    }
}
创建运行时类的对象

通过反射创建对应的运行时类对象

 public void test1() throws Exception {
        Class clazz = Persion.class;
        /*
        newInstance():调用此方法,创建对应的运行时类的对象,内部调用的时运行时类的空参的构造器

        要想次方法正常的创建运行时类的对象,要求:
        1.运行时类必须要提供一个空参的构造器
        2.空参的构造器的访问权限得够,通常设置为public

        在javabean中要求提供一个public的空参构造器。原因:
        1.便于通过反射进行创建运行时的对象
        2.便于子类继承此运行时类时,默认调用的时super()时,保证父类有这个构造器
         */
        Object obj = clazz.newInstance();
        System.out.println(obj);
    }


 @Test
    public void test2() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        int num = new Random().nextInt(3);
        String classpath = "";
        switch (num){
            case 0:
                classpath = "java.util.Date";
                break;
            case 1:
                classpath = "java.lang.Object";
                break;
            case 2:
                classpath = "guiguTest.Persion";
                break;
        }
        Object boj = getInstance(classpath);
        System.out.println(boj);
    }
    public Object getInstance(String classpaath) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName(classpaath);
        return clazz.newInstance();
    }
动态语言和静态语言

1.动态语言:
是一类在运行时可以改变自己的结构的语言:例如新的函数,对象,甚至时代码可以被改进,已有的函数可以被删除或是其他结构上的变化,通俗点讲就是在运行时代码可以根据某些条件改变自身结构
例如:Object-C、C#、javaScript、PHP、Python、Erlang

2.静态语言
与动态语言相对,运行时,结构不可边的语言就是静态语言,如:java C C++

注意:java不是动态语言,但是java可以称之为"准动态语言"。即java有一定的动态性,我们可以利用反射的机制、字节码操作获得雷士动态语言的特性。java的动态性让编程的时候更加灵活

获取当前运行类的属性结构

1.获取属性结构

@Test
public void test1(){
    Class clazz = Persion.class;
    Field[] fields = clazz.getFields();
    //getFields():获取当前运行时类及其父类中声明为public访问修饰符的属性(field -->属性、字段)
    for(Field f : range fields){
        System.out.println(f);
    }
    //获取当前类中声明的所有属性,不含有父类中声明的属性
    Fields[] field1 = clazz.getDeclaredFields();
}

2.获取权限修饰符、数据类型、变量名

//权限修饰符
int modifier = field.getModifiers();
返回的是数字
System.out.println(Modifier.toString(modifier));
//数据类型
Class type = field.getType();
System.out.println(type.toString());
//变量名
String fname = field.getName();

3.获取运行时类方法结构

//获取当前运行时类以及所有父类中声明为public的方法
Method[] methods = clazz.getMethods();
//获取当前运行时类中生声明的方法不包含父类:getDeclaredMethods();

/*权限修饰符 返回值类型 方法名(形参类型1 形参类型2)*/
methods.getModifiers();
methods.getReturnType();
methods.getName();
methods.getParameterTypers();

4.获取运行时类构造器

Constructor[] constructors = clazz.getConstructors();//同上public
getDeclareConstructor();

5.获取运行时的父类

getSuperClass();

6.两需要掌握的
如何操作运行时类中只当的属性–>掌握

Class clazz = Persion.class;
Persion p = (Persion)clazz.newInstance();
//获取指定的属性
Field field = clazz.getFiled(String field);//只能拿到public和默认属性的
Field field1 = clazz.getDeclareField(String field);//可以拿到私有的,但是不能就行修改(因为有封装)需要进行修改
修改:
    //设置属性为可以访问的
   field1.setAccessible(true);
   //在进行修改
   field1.set(p,"tom")

如何操作运行时类的指定方法 -->需要掌握

Method method = clazz.getMethod(String method);
method = clazz.getDeclareMethod(String name,...args形参列表)
   /*invoke():调用方法
   invoke()方法的返回值就是invoke调用方法的返回值
   */
    method.setAccessible(true);
    method.invoke(形参一:方法的调用者,形参二:给形参赋值的实参);
/**
注意:如果调用的方法是没有返回值的返回的就是null
调用静态方法、静态属性需要写的invoke形参时Persion.class
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值