复习(基础7)反射

目录

1、反射概述

1.1、概述

1.2、反射的关键

2、反射获取类对象

3、反射获取构造器对象

4、反射获取成员变量对象

5、反射获取方法对象

6、反射的作用


1、反射概述

1.1、概述

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。

在运行时,可以直接得到这个类的构造器对象:Constructor

在运行时,可以直接得到这个类的成员变量对象:Field

在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

1.2、反射的关键

反射的第一步都是先得到编译后的Class类对象,然后可以得到Class的全部成分。

 

2、反射获取类对象

 

 

获取Class类的对象的三种方式

方式一:Class c1 = Class.forName(“全类名”);

方式二:Class c2 = 类名.class

方式三:Class c3 = 对象.getClass();

package com.itwpf.d2_reflect_class;

public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("无参构造");
    }

    public Student(String name, int age) {
        System.out.println("有参构造");
        this.name = name;
        this.age = age;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public void run(){
        System.out.println("跑得快");
    }
    public void eat(){
        System.out.println("吃得多");
    }
    public String eat(String name){
        System.out.println("吃"+name);
        return "吃得很开心";
    }
}

 

package com.itwpf.d2_reflect_class;

public class Test {
    public static void main(String[] args) throws Exception {

        //1.Class类中的一个静态方法:foeName(全限名:包名+类名)
        Class c = Class.forName("com.itwpf.d2_reflect_class.Student");
        System.out.println(c);

        //2.类名.class
        Class<Student> c2 = Student.class;
        System.out.println(c2);

        //3.对象.getClass()获取对象对应类的Class对象
        Student s = new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c3);
    }

}

3、反射获取构造器对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取构造器的方法 

方法

说明

Constructor<?>[] getConstructors​()

返回所有构造器对象的数组

(只能拿public的)

Constructor<?>[] getDeclaredConstructors​()

返回所有构造器对象的数组,

存在就能拿到

Constructor<T> getConstructor​(Class<?>... parameterTypes)

返回单个构造器对象

(只能拿public的)

Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes)

返回单个构造器对象,

存在就能拿到

package com.itwpf.d2_reflect_class;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class Test02 {

    @Test
    public void getConstruct(){
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.提取类中全部的构造器对象(这里只能拿public修饰的构造器)
        Constructor[] constructors = c.getConstructors();
        //3.遍历构造器
        for(Constructor constructor:constructors){
            System.out.println(constructor.getName()+"==>"+constructor.getParameterCount());
        }
    }
    @Test
    public void getDeclaredConstructors(){
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.提取类中全部的构造器对象
        Constructor[] constructors = c.getDeclaredConstructors();
        //3.遍历构造器
        for(Constructor constructor:constructors){
            System.out.println(constructor.getName()+"==>"+constructor.getParameterCount());
        }
    }
    @Test
    public void getConstructor() throws NoSuchMethodException {
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.定位单个构造器对象
        Constructor<Student> cons = c.getConstructor();
        //3.遍历构造器
        System.out.println(cons.getName()+"==>"+cons.getParameterCount());
    }
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.定位单个构造器对象
        Constructor<Student> cons = c.getDeclaredConstructor();
        //3.遍历构造器
        System.out.println(cons.getName()+"==>"+cons.getParameterCount());

        //定位某个有参构造器
        Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(cons1.getName()+"==>"+cons1.getParameterCount());
    }
}

Constructor类中用于创建对象的方法

符号

说明

T newInstance​(Object... initargs)

根据指定的构造器创建对象

public void  setAccessible(boolean flag)

设置为true,表示取消访问检查,

进行暴力反射

package com.itwpf.d2_reflect_class;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test03 {
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.定位单个构造器对象
        Constructor<Student> cons = c.getDeclaredConstructor();
        //3.遍历构造器
        System.out.println(cons.getName()+"==>"+cons.getParameterCount());

        //如果遇到了私域的构造器,可以暴力反射
        cons.setAccessible(true);//权限被打开
        Student s = cons.newInstance();
        System.out.println(s);


        //定位某个有参构造器
        Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(cons1.getName()+"==>"+cons1.getParameterCount());

        Student ss = (Student)cons1.newInstance("孙", 1000);
        System.out.println(ss);
    }
}

4、反射获取成员变量对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取成员变量的方法

方法

说明

Field[] getFields​()

返回所有成员变量对象的数组(只能拿public的)

Field[] getDeclaredFields​()

返回所有成员变量对象的数组,存在就能拿到

Field getField​(String name)

返回单个成员变量对象(只能拿public的)

Field getDeclaredField​(String name)

返回单个成员变量对象,存在就能拿到

获取成员变量的作用依然是在某个对象中取值、赋值

Field类中用于取值、赋值的方法

符号

说明

void set​(Object obj, Object value)

赋值

Object get​(Object obj)

获取值。

package com.itwpf.d2_reflect_class;

import org.junit.Test;

import java.lang.reflect.Field;

public class Test04 {
    @Test
    public void TestgetFields(){
        Class<Student> c = Student.class;
        Field[] declaredFields = c.getDeclaredFields();

        for(Field f:declaredFields){
            System.out.println(f.getName()+"==>"+f.getType());

        }

    }
    @Test
    public void TestgetField() throws NoSuchFieldException, IllegalAccessException {
        Class<Student> c = Student.class;
        Field d = c.getDeclaredField("name");
        System.out.println(d.getName()+"==>"+d.getType());

        Student s = new Student();
        d.setAccessible(true);
        d.set(s,"100");
        String k = (String)d.get(s);
        System.out.println(k);


    }
}

5、反射获取方法对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取成员方法的方法

方法

说明

Method[] getMethods​()

返回所有成员方法对象的数组

(只能拿public的)

Method[] getDeclaredMethods​()

返回所有成员方法对象的数组,

存在就能拿到

Method getMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象

(只能拿public的)

Method getDeclaredMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象,

存在就能拿到

Method类中用于触发执行的方法

符号

说明

Object invoke​(Object obj, Object... args)

运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数

             (如果没有就不写)

返回值:方法的返回值(如果没有就不写)

package com.itwpf.d2_reflect_class;

import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test05 {
    @Test
    public void getDeclaredMethods(){
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.提取全部方法,包括私有
        Method[] methods = c.getDeclaredMethods();
        //3.遍历全部方法
        for(Method m:methods){
            System.out.println(m.getName()+",返回值类型"+m.getReturnType()+",参数个数"+m.getParameterCount());
        }
    }

    @Test
    public void getDeclaredMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.获取类对象
        Class<Student> c = Student.class;
        //2.提取全部方法,包括私有
        Method m = c.getDeclaredMethod("eat");
        Method m2 = c.getDeclaredMethod("eat",String.class);
        //3.遍历方法
        System.out.println(m.getName()+",返回值类型"+m.getReturnType()+",参数个数"+m.getParameterCount());
        System.out.println(m2.getName()+",返回值类型"+m2.getReturnType()+",参数个数"+m2.getParameterCount());

        //暴力反射
        m2.setAccessible(true);
        //触及方法的执行
        Student s = new Student();
        //注意:方法如果是没有结果回来,那么返回的是null
        Object invoke = m2.invoke(s,"hello");
        System.out.println(invoke);
    }
}

6、反射的作用

反射的作用-绕过编译阶段为集合添加数据

反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的

泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。

package com.itwpf.d2_reflect_class;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class ReflectDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        System.out.println(list1.getClass());
        System.out.println(list2.getClass());
        System.out.println(list1.getClass() == list2.getClass());


        list2.add(23);
        list2.add(24);
        Class<? extends ArrayList> c = list2.getClass();
        Method method = c.getDeclaredMethod("add",Object.class);
        method.invoke(list2,"hello");
        System.out.println(list2);

        ArrayList list3 = list2;
        list3.add("nihao");
        System.out.println(list2);
    }
}


运行结果:
    class java.util.ArrayList
    class java.util.ArrayList
    true
    [23, 24, hello]
    [23, 24, hello, nihao]

        反射是作用在运行时的技术,此时已经不存在泛型了。

        可以在运行时得到一个类的全部成分然后操作。

        可以破坏封装性。(很突出)

        也可以破坏泛型的约束性。(很突出)

        更重要的用途是适合:做Java高级框架

        基本上主流框架都会基于反射设计一些通用技术功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值