Class类

1、一个类的正常流程:
在这里插入图片描述
内存中有很多这在运行的类,比如Person类,Student类等

2、含义
java是面向对象的方法,所以所有的事物都可以看做一个类,那么内存中的那些类都是事物,整体就可以再被认为是一个类,而具体的某一个Person类,或者Student类就可以看作是他的对象
所以java使用了一个类描述内存中正在运行的class对象,这个类是java.lang.class
在这里插入图片描述

3、作用
Class类创建了对象Person类,就可以操作内存中的Person.class文件
比如:
获取成员变量 并赋值
成员方法 运行
构造方法 运行
用Class类去操作Person.class的过程叫做反射

4、如何获取运行时类的字节码文件对象
运行时的字节码:在方法区中的Person.class文件
1、Object类的getClass方法
Person p=new Person();
p.getClass();

2、类的静态class属性
Person.class()

3、Class类静态方法 forName(“类名”)
Class.forName(“com.doit.Person”)//Person类太多了,必须具体到哪个包下面的Person

推荐3,因为实现了解耦,将字符串解耦出来

5、完成使用Properties获取className

   //创建Properties对象,将里面的设置内容读进来
    Properties properties = new Properties();
    FileReader fileReader = new FileReader("/Users/Downloads/className.properties");
    //在/Users/Downloads/className.properties文件里面设置 className=com.doit.Person
    properties.load(fileReader);
    System.out.println(properties);

    String className=properties.getProperty("className");
    //获取字节码文件对象
    Class aClass = Class.forName(className);
    //所以最后想要获取哪个字节码文件对象,可以直接修改properties里面的calssName内容

6、反射获取构造方法
1、获取字节码文件对象
2、获取构造方法
3、运行构造方法

public class TEST {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    //前面4个方法是获取构造方法
        method1(); 
        method2();
        method3();
        method4();
      //获取空参构造方法,然后运行空参构造
        method5();
       //获取带参构造方法,然后运行带参构造
       method6();
       //获取私有构造方法,然后运行构造方法,暴力方法,了解即可
       method7();
    }
    /*
     获取所有的公共的构造方法
    Constructor[] getConstructor()此Class对象所表示的类的所有公共构造方法
     */
    public static void method1() throws ClassNotFoundException{
        Class aClass = Class.forName("test.Person");
        Constructor[] cons= aClass.getConstructors();
        for(Constructor con:cons){
            System.out.println(cons);
        }
    }

    /*
     获取所有的构造方法,包括私有
    Constructor<T>[] getDeclaredConstructors 此Class对象表示的类声明的所有构造方法
     */
    public static void method2() throws ClassNotFoundException{
        Class aClass = Class.forName("test.Person");
        Constructor[] cons= aClass.getDeclaredConstructors();
        for(Constructor con:cons){
            System.out.println(cons);
        }
    }
    /*
     获取指定的非私有的空参构造方法
    Constructor getConstructor()
    */
    public static void method3() throws  ClassNotFoundException, NoSuchMethodException {
        Class aClass = Class.forName("test.Person");
        Constructor cons = aClass.getConstructor();
        System.out.println(cons);
    }
    /*
     获取指定的非私有的带参构造方法
    Constructor getConstructor(Class ... params) 参数是:Class类型的参数
    */
    public static void method4() throws  ClassNotFoundException, NoSuchMethodException {
        Class aClass = Class.forName("test.Person");
        Constructor cons = aClass.getConstructor(String.class,int.class);
        System.out.println(cons);
    }

    /*
    获取空参构造方法
   Constructor getConstructor()
    然后运行空参构造方法:
        public T newInstance()
   */
    public static void method5() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //获取空参构造方法
        Constructor cons = aClass.getConstructor();
        System.out.println(cons);
        //运行空参构造
        Object o = cons.newInstance(); //相当于Object o =new Person();
        //这个方法和一般的new方法的区别在于,这个方法可以通过修改字节码对象来修改创建的对象
        System.out.println(o);
    }

  /*
获取带参构造方法
Constructor getConstructor(参数列表)
然后运行带参构造方法(Constructor下的方法)
    public T newInstance(Object...args)运行带参构造,需要制定运行构造方法的实际参数
*/
    public static void method6() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //获取带参构造方法
        Constructor cons = aClass.getConstructor(String.class,int.class);
        System.out.println(cons);
        //运行带参构造
        Object o = cons.newInstance("张三",18); //相当于Object o =new Person();
        //这个方法和一般的new方法的区别在于,这个方法可以通过修改字节码对象来修改创建的对象
        System.out.println(o);
    }
 /*
     获取私有构造方法(暴力反射 不安全 了解即可)
        getDeclaredConstructor(参数列表)
     取消反射对象的访问权限检查
       方法:
       java.lang.reflect.AccessibleObject
       void setAccessible(boolean flag) flag为true则取消反射对象的访问权限检查
       因为Constructor 继承了AccessibleObject,所以可以直接调用
     运行私有构造方法:
        public T newInstance(Object...args)
     */
    public static void method7() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
       //获取字节码对象
        Class aClass = Class.forName("test.Person");
        //获取当前字节码的私有构造方法
        Constructor cons = aClass.getDeclaredConstructor(String.class);
        //取消反射对象的访问权限检查,true 取消访问权限检查
        cons.setAccessible(true);
        //运行私有构造方法
        //如果没有上面的取消权限检查这一步会报错。cons可以访问到,但是无法运行,因为获取到的构造方法是私有的
        Object o = cons.newInstance("张三");
        System.out.println(o);
    }
}
/*
* 快捷方式 反射创建对象
* Class 类
*   public T newInstance() 通过字节码对象,直接运行空参构造方法
* 使用前提:
*   1、这个类必须具备空参构造
*   2、必须有访问权限
* 对比之前的方法是利用的Constructor 下的 newInstance()方法
* */
public class TEST {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class aClass = Class.forName("test.Person");
        Object o = aClass.newInstance();
        System.out.println(o);
    }
}

7、反射获取方法
1、获取字节码文件对象
2、获取方法
3、运行方法

//以下内容主要是获取方法,运行方法的内容参考下一段代码
public class TEST {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        method1();
        method2();
        method3();
        //重点掌握method4()
        method4();
    }

    /*
     * 获取类的所有公共方法,包括继承来的方法
     * Class类
     *      Method[]  getMethods()
     * */
    public static void method1() throws ClassNotFoundException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //调用方法,当前字节码文件对象,所表示类中所有公共的方法,包括继承
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

    /*
     * 获取类的所有公共方法,包括私有,不包括继承来的方法
     * Class类
     *      Method[]  getDeclaredMethods()
     * */
    public static void method2() throws ClassNotFoundException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //调用方法,当前字节码文件对象,所表示类中公共方法,包括私有,不包括继承
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

    /*
     * 获取类指定的无参数的方法
     * Class类
     *      Method getMethod(String name);
     *      String name:方法名称
     * */
    public static void method3() throws ClassNotFoundException, NoSuchMethodException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //调用方法,当前字节码文件对象,所属类的指定的无参数的方法
        Method method = aClass.getMethod("eat");
        System.out.println(method);
    }

    /*
     * 获取类指定的方法
     * Class类
     *      Method getMethod(String name,Class...params);//获取指定的方法
     *      String name:方法名称
     *      Class...params:方法的参数的数据类型
     * */
    public static void method4() throws ClassNotFoundException, NoSuchMethodException {
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //调用方法,当前字节码文件对象,所属类的指定的方法
        Method method = aClass.getMethod("setName", String.class);
        System.out.println(method);
    }
}
//重点是运行方法
public class TEST {
    public static void main(String[] args) throws Exception {
        method();
    }
    /*
     * 1、获取字节码文件对象
     * 2、获取类指定的方法
     * Class类
     *      Method getMethod(String name,Class...params);//获取指定的方法
     *      String name:方法名称
     *      Class...params:方法的参数的数据类型
     *
     * 2、运行方法
     *      public Object invoke(Object obj,Object...args)
     *      返回值类型Object:运行方法的返回值,使用Object接收,如果方法没有返回值则返回Null
     *      参数Object obj:运行方法需要有对象支持,可以说new对象,但是这种方式不好,没有利用反射解耦
     *                      所以可以考虑使用快捷方式 创建对象,cons.newInstance()
     *      参数Object...args:运行的方法如果有参数,需要给定具体的实际参数 比如setName(String name)
     *                        就需要一个"张三"。
     * */

    public static void method() throws Exception{
        //获取字节码文件对象
        Class aClass = Class.forName("test.Person");
        //获取指定的方法setName
        Method method = aClass.getMethod("setName", String.class);
        //快捷方式创建对象
        Object o = aClass.newInstance();
        //运行方法
        Object obj = method.invoke(o, "张三"); 
        System.out.println(obj);//setName没有返回值,所以这里的obj是null
        System.out.println(o);//调用了setName()方法,之后对象o有了name
        
        System.out.println("-----------------------------");
        
        Method getNameMethod = aClass.getMethod("getName");
        //运行方法
        Object name = getNameMethod.invoke(o);//getName方法没有参数,所以不需要传入具体地址
        System.out.println(name);//getName有返回值,返回值为String name
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值