java反射

面试题
谈谈 java 的反射机制?
学习目标
掌握 java 的反射机制
学习内容


1、反射

运行状态 中,对于任意一个类能够获取类中的所有属性和方法,对于任意一个对象能够调用对象中的属性和方 法,这种动态获取属性和方法的机制:反射。
java 程序的运行原理:

 反射的步骤:

第一步:获取 Class 类的实例 :
1 、类名 .class
2 new Object().getClass
3 Class.forName(" 类的完全限定名 ");
注意:获取到的 Class 类型的实例在内存是唯一的,推荐使用: Class.forName(" 类的完全限定名 ")
  public static void main(String[] args) {
// 获取Class类型的实例
            Class<User> aClass = User.class;
            User user=new User();
            Class<? extends User> aClass1 = user.getClass();
            Class<?> aClass2=null;
            try {
                aClass2= Class.forName("com.aaa.entity.User");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            System.out.println(aClass==aClass1);
            System.out.println(aClass1==aClass2);
  }
三种方式的特征:
(1 )类名 .class JVM 将使用类装载器,将类装入内存 ( 前提是 : 类还没有装入内存 )
  不做类的初始化工作,返回 Class 的对象。
2 Class.forName(“ 类名字符串 ”) :装入类,并做类的静态初始化,返回 Class 的对象。
3 )实例对象 .getClass() :对类进行静态初始化、非静态初始化;
  返回引用运行时真正所指的对象 ( 子对象的引用
  会赋给父对象的引用变量中 ) 所属的类的 Class 的对象。
第二步:通过 Class 可以获取构造方法、字段、属性、方法、接口 ....
将类中的构造方法、字段、方法都封装成了单独的类型:
类型
Field
属性
Constructor
构造方法
Method
方法
getConstructors
获取类的所有构造方法
getConstructor()
得到空参的构造方法
getConstructor(String.class,int.class )
得到对应两个参数的构造方法
newInstance()
创建对象
getFields,getDeclaredFields
获取所有属性成员
getField,getDeclaredField
获取单个属性成员
set(Object obj,Object value)
修改成员的值
method.setAccessible(true);
暴力访问
getMethods getDeclaredMethods
获取所有方法
getMethod getDeclaredMethod
获取单个方法
getFields() :获得某个类的所有的公共( public )的字段,包括父类中的字段。 getDeclaredFields() :获得某个类 的所有声明的字段,
即包括 public private proteced ,但是不包括父类的申明字段。
getDeclaredMethod*() 获取的是类自身声明的所有方法,包含 public protected private 方法。
getMethod*() 获取的是类的所有共有方法,这就包括自身的所有 public 方法,和从 基类 继承的、从接口实现的所有
public 方法。

获取构造方法
实例 1:

    public static void main(String[] args) throws ClassNotFoundException {
        // 获取Class类型的实例
        Class<User> clz = User.class;
        try {
// 获取指定的构造方法
// Constructor<User> cs=clz.getConstructor();
// 借助于构造方法创建对象
// User user= cs.newInstance();
// 获取带参数的构造方法
            Constructor<User> cs =
                    clz.getConstructor(Integer.class, String.class, String.class);
// 给构造方法传递参数
            User user = cs.newInstance(100, "小强", "123");
            获取字段:
            System.out.println(user);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        try {
// 创建一个对象
            User user = clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
// 获取所有的公共的构造方法
// Constructor[] cs1=clz.getConstructors();
// for (int i = 0; i < cs1.length; i++) {
// Constructor constructor = cs1[i];
// System.out.println(constructor);
// }
// System.out.println("-----------------");
// 获取所有的构造方法
// Constructor[] cs2=clz.getDeclaredConstructors();
// for (int i = 0; i < cs2.length; i++) {
// Constructor constructor = cs2[i];
// System.out.println(constructor);
// }
    }


}
获取字段:
public static void main(String[] args) {
// UserService userService=new UserServiceImpl();
// Object obj=userService.queryAll(1,5,new User());
// System.out.println(obj.getClass());
        Class<User> userClass = User.class;
// Field[] fields = userClass.getDeclaredFields();
// for (int i = 0; i < fields.length; i++) {
// Field field = fields[i];
// System.out.println(field);
// }
        try {
            User user = userClass.newInstance();
            Field id = userClass.getDeclaredField("id");
// 暴力破解:允许访问
            id.setAccessible(true);
            id.set(user,100);
            System.out.println(id.get(user));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

获取方法:
public static void main(String[] args) throws ClassNotFoundException {
        public static void main(String[] args) {
            try {
                Class<?> aClass = Class.forName("com.mrlang.service.UserServiceImpl");
// 获取class对应的UserServiceImpl的对象
                Object instance = aClass.newInstance();
                Method queryAll = aClass.getMethod("queryAll", Integer.class,
                        Integer.class, User.class);
// 调用方法
                PageBean result= (PageBean) queryAll.invoke(instance,1,3,new User());
                System.out.println(result);
// 获取所有公有的方法
/* Method[] methods= aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}*/
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
反射的作用:
示例 1 :在配置文件中配置要实例化的类型信息,使用反射得到实例:

  public class Student {
            private int id;
            private String sname;
            private String sex;
            private String addr;

            public Student() {
            }

            public Student(int id, String sname, String sex, String addr) {
                this.id = id;
                this.sname = sname;
                this.sex = sex;
                this.addr = addr;
            }

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public String getSname() {
                return sname;
            }

            public void setSname(String sname) {
                this.sname = sname;
            }

            public String getSex() {
                return sex;
            }

            public void setSex(String sex) {
                this.sex = sex;
            }

            public String getAddr() {
                return addr;
            }

            public void setAddr(String addr) {
                this.addr = addr;
            }

            public boolean sleep(String name) {
                System.out.println(name + "又在睡觉了");
                return false;
            }

            @Override
            public String toString() {
                return "Student{" +
                        2、代理
                举例:
                租房
                屋主A(出租 / 卖) (目标对象)-- > 中介(看房)(代理对象) <--租户(用户)
                屋主B(出租) (目标对象)
                        代理模式:
                "id=" + id +
                        ", sname='" + sname + '\'' +
                        ", sex='" + sex + '\'' +
                        ", addr='" + addr + '\'' +
                        '}';
            }

            className=
            com.aaa.entity.Student
                    methodName = sleep

            public class Test {
                public static void main(String[] args) throws IOException, ClassNotFoundException,
                        IllegalAccessException, InstantiationException, NoSuchMethodException,
                        InvocationTargetException {
                    Properties pro = new Properties();
/* //获取当前的类加载器
类加载器(class loader)用来加载java类到java虚拟机
InputStream is = 类
名.getClass().getClassLoader().getResourceAsStream("helloworld.properties");
类名.Class: 是获取这个类的Class对象
getClassLoader:获取该Class对象的类加载器,
最后,类加载器的getResourceAsStream()方法来加载资源。*/
                    ClassLoader cl = Test.class.getClassLoader();
                    InputStream is = cl.getResourceAsStream("files.properties");
                    pro.load(is);
                    String cname = pro.getProperty("className");
                    String methodName = pro.getProperty("methodName");
                    System.out.println(cname + "," + methodName);
                    Class cls = Class.forName(cname);//加载进类的内存
                    Object obj = cls.newInstance();//创建对象
                    Method method = cls.getMethod(methodName, String.class);//获取方法对象
                    Object r = method.invoke(obj, "tom");
                    System.out.println(r);
                }

            }
        }

最后附上实例

首先先建立一个父类

public class Goods {
    public String type;

    public Goods() {
    }

    public Goods(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "type='" + type + '\'' +
                '}';
    }
}

新建books实体类对象继承父类Goods

public class Books extends Goods {
    private Integer bid;
    public String title;
    private double price;

    static
    {
        System.out.println("静态代码块执行了");
    }
    {
        System.out.println("普通代码块执行了");
    }
    public Books() {
        System.out.println("空参构造方法执行了");
    }

    public Books(Integer bid, String title, double price) {
        this.bid = bid;
        this.title = title;
        this.price = price;
    }

    public Integer getBid() {
        return bid;
    }

    public void setBid(Integer bid) {
        this.bid = bid;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Books{" +
                "bid=" + bid +
                ", title='" + title + '\'' +
                ", price=" + price +
                '}';
    }
}

获取类对象实例

/*
*得到一个类的class实例的三种方式
* 1、类名.class
2、new Object().getClass
3、Class.forName("类的完全限定名");
* */
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取books类的class实例
        //方式一:
//        Class<Books> booksClass1 = Books.class;
        //方式二:
        Books books = new Books();
        Class booksClass2 = books.getClass();
        //方式三:
//        Class booksClass3 = Class.forName("com.aaa.Reflect.Books");
//        System.out.println(booksClass1);
//        System.out.println(booksClass2);
//        System.out.println(booksClass3);
//
//        System.out.println("========================");

//        System.out.println(booksClass1==booksClass2);
//        System.out.println(booksClass1==booksClass3);
//        System.out.println(booksClass2==booksClass3);


    }
}

/*
class的常用方法
----------------------------
field:属性
method:方法
Constructor:构造方法
-------------------------------
getConstructors获取类的所有构造方法
getConstructor()得到空参的构造方法
getConstructor(String.class,int.class )得到对应两个参数的构造方法
newInstance()创建对象
* */
public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //第一步:得到book的class实例
        Class bClass = Class.forName("com.aaa.Reflect.Books");
        //第二步:根据class获取对应的构造方法
        Constructor[] bc = bClass.getConstructors();//得到books类内部的所有构造方法
        if (bc!=null)
        {
            for (Constructor c : bc)
            {
                System.out.println(c);
            }
        }
        System.out.println("========================");

        Constructor<Books> c1 = bClass.getConstructor();
        System.out.println("空参数的构造为:"+c1);
        Books b = c1.newInstance();//利用该构造方法创建 该类的对象
        System.out.println("利用反射创建出来的books的实例对象为:"+b);

        System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");

        Constructor<Books> c2 = bClass.getConstructor(Integer.class,String.class,
                double.class);
        System.out.println("三个参数的构造为:"+c2);
        Books b2 = c2.newInstance(12,"JAVA高级特性",99.8);
        System.out.println("利用反射创建出来的books的实例对象为:"+b2);
    }

}

/*
getFields,getDeclaredFields获取所有属性成员
getField,getDeclaredField获取单个属性成员
getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,
但是不包括父类的字段。
 */
public class Demo3 {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一步:得到book的class实例
        Class<Books> booksClass = (Class<Books>) Class.forName("com.aaa.Reflect.Books");
        //第二部:获取Field属性
        Field[] bfs = booksClass.getFields();
        if (bfs!=null)
        {
            for (Field f:bfs)
            {
                System.out.println("AAA:"+f);
            }
        }
        System.out.println("===========================");
        //第二部:获取field属性
        Field [] bfs2 = booksClass.getDeclaredFields();
        if (bfs!=null)
        {
            for (Field f:bfs2)
            {
                System.out.println(f);
            }
        }
    }
}

/*
getFields,getDeclaredFields获取所有属性成员
getField,getDeclaredField获取单个属性成员
getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,
但是不包括父类的字段。
 */
public class Demo4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //第一步:得到book的class实例
        Class<Books> booksClass = (Class<Books>) Class.forName("com.aaa.Reflect.Books");
        Constructor <Books> bc=booksClass.getConstructor(Integer.class,String.class,double.class);
        //利用构造,创建该book的对象
        Books books = bc.newInstance(9,"MYSQL",88.8);
        //第二部:获取field属性
        Field [] bfs = booksClass.getFields();
        if (bfs!=null)
        {
            for (Field f:bfs)
            {
                System.out.println(f);
            }
        }
        System.out.println("=======================================");
        //第二部:获取field属性
        Field [] bfs2 = booksClass.getDeclaredFields();
        if (bfs!=null)
        {
            for (Field f: bfs2)
            {
                System.out.println(f);
            }
        }
        System.out.println("*************************************");

        Field fId = booksClass.getDeclaredField("bid");
        fId.setAccessible(true);//允许暴力访问,若要获取一个私有类型的值,需要设置该属性允许暴力访问
        System.out.println(fId.get(books));//得到执行的实例对象里的title属性的值
        Field fTitle = booksClass.getField("title");
        System.out.println(fTitle.get(books));//得到执行的实例对象里的title属性的值


    }
}

这里再附上反射加泛型的一些案例

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

public class day1 {
    public static void main(String[] args) {
        //第一步:得到BookDaoimpl的clss实例
        try {
            Class<?> bClass = Class.forName("com.aaa.Reflect_Two.BookDaoImpl");
            //第二步:利用getMethod得到该类里边的对应方法的对象 参数一:add:被调用的方法名称
            //后边的所有参数为被调用的方法的所有参数的class实例
            //        String title,String author,double price
            try {
                Method addM = bClass.getMethod("add",String.class,String.class,double.class);
                //第三步:执行方法 参数一:当前方法所在类的实例对象 后边的参数为被调用
                //方法所需要的所有参数的值
                try {
                    try {
                        boolean result = (boolean) addM.invoke(bClass.newInstance(),
                                "C#","杜甫",35.8);
                        System.out.println("add方法的执行结果为:"+result);
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
mport com.aaa.Reflect_Two.Book_Two;
import com.aaa.Reflect_Two.Goods;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class day2 {
    //在方法上边使用泛型,需要在方法的返回值前边加上类型的占位符<K>
    public <V> V getInstance(Class<V> eClass)
    {
        //第一步:利用类的class实例创建该类的对象
        //getConstructors获取类的所有构造方法并且newInstance()创建对象
        V obj = null;
        try {
            obj = eClass.getConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        try {

            //第二步:获取该类的所有的属性
            Field [] fs =eClass.getDeclaredFields();
            //第三步:循环遍历所有属性
            for (Field f:fs)
            {
                //允许暴力访问,若要获取一个私有类型的值,需要设置该属性允许暴力访问
                f.setAccessible(true);//允许给私有的属性进行值的设置
                if (f.getName().equals("id"))
                {
                    f.set(obj,11);
                }
                if (f.getName().equals("title"))
                {
                    f.set(obj,"MySql");
                }
                if (f.getName().equals("author"))
                {
                    f.set(obj,"白居易");
                }
                if (f.getName().equals("price"))
                {
                    f.set(obj,88.5);
                }
                //f.set(obj,1);//给传递进来的类的对象的所有属性的值都设置为1
                if (f.getName().equals("id"))
                {
                    f.set(obj,1);
                }
                if (f.getName().equals("gName"))
                {
                    f.set(obj,"薯片");
                }
//                if (f.getName().equals("price"))
//                {
//                    f.set(obj,12.5);
//                }
                if (f.getName().equals("num"))
                {
                    f.set(obj,88);
                }
            }
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return obj;
    }

    public static void main(String[] args) {
        day2 day2 =new day2();
        Book_Two b = day2.getInstance(Book_Two.class);
        System.out.println(b);
        Goods g = day2.getInstance(Goods.class);
        System.out.println(g);
    }
import java.util.ArrayList;
import java.util.List;

public class day3 {
    public <K> void test1(List<K>list)
    {
        K o = list.get(1);
        System.out.println("test1:"+list);
    }

    public void test2(List<?>list)
    {
//         ? a = list.get(0);
        System.out.println("test2:"+list);
    }

    //<? extends Goods>:传递的参数的集合数据可以是Goods类型及Goods类型的子类
    public void test3(List<? extends Goods> list)
    {
        for (Goods e:list)
        {
            System.out.println(e);
        }
    }

    //<? super Book_Two>:传递的参数的数据可以是Book_Two类型或者Book_Two类型的父类
    public void test4(List<? super Book_Two>list)
    {
        for (Object o : list)
        {
            System.out.println(o);
        }
    }

    public static void main(String[] args) {
        day3 day3 =new day3();
        List<String> list =new ArrayList<>();
        list.add("太极");
        list.add("刚柔并济");
        day3.test1(list);
        day3.test2(list);
        System.out.println("==================");
        List<Integer>list2 = new ArrayList<>();
        list2.add(1);
//        list2.add(Integer.parseInt("22"));
        list2.add(Integer.parseInt("22222"));
        day3.test1(list2);
        day3.test2(list2);

        System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
        List<Book_Two>list3 = new ArrayList<>();
        list3.add(new Book_Two());
        list3.add(new Book_Two());
        List<Goods> list4 = new ArrayList<>();
        list4.add(new Goods());

        System.out.println("****************************");

        day3.test3(list4);
        day3.test3(list3);
        day3.test4(list3);
        day3.test4(list4);
    }

 


总结

以上就是今天要讲的内容,本文仅仅简单介绍了反射的使用,而反射提供了大量能使我们快速便捷地处理对象的方法,当然,笔者深度欠缺,如有不足还请指正。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

id_lian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值