反射机制初探 *

走进沼泽

在正常的程序中,先有类,然后再有对象。

  • 取得Class对象(类对象)
  1. public final Class<?> getClass() ;
  • 实例观察:
  1. public class TestDemo {
  2. public static void main(String [] args) {
  3. Date date = new Date() ; // 产生对象
  4. System.out.println(date.getClass());
  5. // 因为所有类都是 Object的子类,而getClass是final型所以所有类都有getClass()方法
  6. }
  7. }
  • 运行结果
  1. class java.util.Date

发现:调用getClass()方法输出的是类的完整名称,等于找到了对象出处:

——这就是“

Class 类对象实例化

  • java.lang.Class是一个类,这个类就是反射操作的源头,即:所有的反射都要从Class类开始运行 三种实例化方法;

    • 调用Object中的Class方法
    1. Class<?> cls = date.getClass();
    2. // 此代码将Class类进行了实例化;getClass()是class类的实例化方法
    • 使用 类.class 方法
    1. Class<?> cls = Date.class;

    前者是产生了类的实例化对象之后取得Class类对象,但是类.class方法并没有实例化对象产生

    • 调用Class类提供的 forName() 方法
    1. Class<?> cls = Class.forName(String ClassName) ;

    此时可以不使用 import 语句导入一个明确的类名称,而类名称采用字符串的方式进行描述

反射实例化对象

当获得一个类时,使用关键字 new 进行类对象实例化操作;但是如果有了Class对象,那么就可以利用反射进行对象实例化操作。

实例化对象的方法:

  1. public T newInstance();
  • 实例分析:
  1. class Book {
  2. public Book() {
  3. System.out.println("**********Book类 ***********");
  4. }
  5. @Override
  6. public String toString() {
  7. return "Hello,World!";
  8. }
  9. }
  10. public class TestDemo {
  11. public static void main(String [] args) throws InstantiationException, ReflectiveOperationException {
  12. Class<?> cls = Class.forName("helloworld.Book");
  13. @SuppressWarnings("deprecation")
  14. Object obj = cls.newInstance();
  15. Book book = (Book) obj ;// 向下转型
  16. System.out.println(book);// 调用了Book类的对象
  17. // 此过程没有 new 关键字实例化Book类,而是通过反射来实例化对象
  18. }
  19. }

在反射机制的加持下,类的对象实例化则不再单独依靠 new关键字

  • new 与 反射 实例化对象的区别
  1. package helloworld;
  2. interface Fruit { // 函数是接口
  3. public void eat() ;
  4. }
  5. class Apple implements Fruit {
  6. @Override
  7. public void eat() {
  8. System.out.println("苹果");
  9. }
  10. }
  11. class Factory {
  12. public static Fruit getInstance(String className) {
  13. if ("apple".equals(className)) {
  14. return new Apple();
  15. }
  16. return null ;
  17. }
  18. }
  19. public class TestFactory {
  20. public static void main(String[] args) {
  21. Fruit f = Factory.getInstance("apple");// 实例化Fruit对象
  22. f.eat();
  23. }
  24. }
  • 如果Fruit接口子类被增加了一个,那么就表示程序需要修改工厂类
  1. package helloworld;
  2. interface Fruit { // 函数是接口
  3. public void eat() ;
  4. }
  5. class Apple implements Fruit {
  6. @Override
  7. public void eat() {
  8. System.out.println("苹果");
  9. }
  10. }
  11. class Orange implements Fruit{
  12. @Override
  13. public void eat() {
  14. System.out.println("橘子");
  15. }
  16. }
  17. class Factory {// 工厂类
  18. public static Fruit getInstance(String className) {
  19. if ("apple".equals(className)) {
  20. return new Apple();
  21. } else if ("orange".equals(className)) {
  22. return new Orange();
  23. } else {
  24. return null ;
  25. }
  26. }
  27. }
  28. public class TestFactory {
  29. public static void main(String[] args) {
  30. Fruit f = Factory.getInstance("apple");// 实例化Fruit对象
  31. f.eat();
  32. }
  33. }
  • 如上两则程序可以看出:

    每增加一个类,就要修改工厂类,非常的繁琐复杂;因为工厂类中的对象都是通过new直接实例化,而new就造成了这种高耦合的问题。

  • 解决方法:

    依靠反射实例化对象来完成

    1. package helloworld;
    2. interface Fruit { // 函数是接口
    3. public void eat() ;
    4. }
    5. class Apple implements Fruit {
    6. @Override
    7. public void eat() {
    8. System.out.println("苹果");
    9. }
    10. }
    11. class Orange implements Fruit{
    12. @Override
    13. public void eat() {
    14. System.out.println("橘子");
    15. }
    16. }
    17. class Factory {// 工厂类
    18. @SuppressWarnings("deprecation")
    19. public static Fruit getInstance(String className) throws InstantiationException, ReflectiveOperationException, ClassNotFoundException {
    20. Fruit f = null ;
    21. try {
    22. f = ((Fruit) Class.forName(className).newInstance());
    23. // 因为 Class.forName()方法返回的是Object(默认/推荐),所以需要向下转型为Fruit
    24. } catch (Exception e) { }
    25. return f ;
    26. }
    27. }
    28. public class TestFactory {
    29. public static void main(String[] args) throws InstantiationException, ClassNotFoundException, ReflectiveOperationException {
    30. Fruit f = Factory.getInstance("helloworld.Apple");
    31. f.eat();
    32. }
    33. }
    34. // 程序中出现疑虑,可以参照"实例分析"
  • 此时的程序就完成了解耦和的目的而且可扩展性非常的强

反射调用方法

  • 定义Book类
  1. package helloworld;
  2. public class Book {
  3. private String title ;
  4. public void setTitle(String title) {
  5. this.title = title;
  6. }
  7. public String getTitle() {
  8. return title;
  9. }
  10. }

类中有 无参构造方法 所以实例化对象的时候可以直接利用Class类中的newInstance()方法

  • 在Class类中定义有如下的取得类中Method的操作:

    • 取得类中的全部方法:
    1. public Method [] getMethods();
    • 取得指定类中方法:
    1. public Method getMethod(String className , Class<?>... parameterTypes);

    以上返回的是:java.lang.reflect.Method 类的对象

  • Methos类中的调用方法:

    1. public Object invoke(Object obj , Object args);
  • 实例:

  1. package helloworld;
  2. import java.lang.reflect.Method;
  3. public class TestDemo {
  4. public static void main(String [] args) throws InstantiationException, ReflectiveOperationException {
  5. String classname = "title" ;
  6. Class<?> cls = Class.forName("helloworld.Book");
  7. Object obj = cls.newInstance(); // 给出了Book类的实例化对象
  8. Method setMet = cls.getMethod("set" + initcap(classname),String.class);
  9. Method getMed = cls.getMethod("get" + initcap(classname));
  10. setMet.invoke(obj, "Java");
  11. System.out.println(getMed.invoke(obj));
  12. }
  13. private static String initcap(String str) { // 首字母大写
  14. return str.substring(0,1).toUpperCase() + str.substring(1) ;
  15. }
  16. }

反射调用成员

  • 类中的属性,一定要在本类实例化对象产生之后才可以分配内存空间。

  • 取得全部成员:

    1. public Field [] getDeclaredFields() ;
  • 取得指定成员:

    1. public Field getDeclaredFields() ;
  • 返回的类型:java.lang.reflect.Field 类对象

    • 取得属性内容:
    1. public Object get(Object obj);
    • 设置属性内容:
    1. public void set(Object obj , Object Value);
  • 定义Book类:

  1. package helloworld;
  2. public class Book {
  3. public String title ;
  4. }
  1. package helloworld;
  2. import java.lang.reflect.Field;;
  3. public class TestDemo {
  4. public static void main(String [] args) throws InstantiationException, ReflectiveOperationException {
  5. String classname = "title" ;
  6. Class<?> cls = Class.forName("helloworld.Book");
  7. Object obj = cls.newInstance(); // 给出了Book类的实例化对象
  8. java.lang.reflect.Field titleField = cls.getDeclaredField("title") ;
  9. titleField.set(obj, "Java");
  10. System.out.println(titleField.get(obj));
  11. }
  12. }
  • 另外,还有一个访问private私有成员的方法,利用 setAccessible() 方法取消封装,然后调用成员。
  1. package helloworld;
  2. import java.lang.reflect.Field;;
  3. public class TestDemo {
  4. public static void main(String [] args) throws InstantiationException, ReflectiveOperationException {
  5. String classname = "title" ;
  6. Class<?> cls = Class.forName("helloworld.Book");
  7. Object obj = cls.newInstance(); // 给出了Book类的实例化对象
  8. Field titleField = cls.getDeclaredField("title") ;
  9. titleField.setAccessible(true);// 取消封装
  10. titleField.set(obj, "Java");
  11. System.out.println( titleField.get(obj) );
  12. }
  13. }

构造方法和普通方法,也同样可以取消封装,但很少使用。

总结

  • 实例化对象的方法增加一种“反射”
  • 反射调用类机构只是一个开始

Java 反射机制 初探*的更多相关文章

  1. java反射机制初探

    最近和一位师兄交流了一下Java,真可谓是大有收获,让我好好的学习了一下javad的反射机制,同终于明白了spring等框架的一个基本实现的思想,那么今天就和大家分享一下java的反射机制. 反射,r ...

  2. java反射机制初探

    最近和一位师兄交流了一下Java,真可谓是大有收获,让我好好的学习了一下javad的反射机制,同终于明白了spring等框架的一个基本实现的思想,那么今天就和大家分享一下java的反射机制. 反射,r ...

  3. 初探Java反射机制

    反射库提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序库.这项功能被大量地应用于JavaBeans中.反射机制提供了在运行状态中获得和调用修改任何一个类的属性和方法的能力. ...

  4. Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

    IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更 ...

  5. 浅谈java反射机制

    目录 什么是反射 初探 初始化 类 构造函数 属性 方法 总结 思考 什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意 ...

  6. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  7. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  8. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  9. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

随机推荐

  1. JS---封装缓动(变速)动画函数---增加多个任意多个属性

    封装缓动动画函数---增加多个任意多个属性 在原来缓动动画函数,增加任意一个属性的基础上,做了如下改变 1. 原来function animate(element, attr, target),三个变 ...

  2. JQuery 基本使用、操作样式、简单动画

    JQ与JS JQ是JS写的插件库,就是一个JS文件 凡是用JQ能实现的,JS都能实现,JS能实现的,JQ不一定能实现 引入 BootCDN:https://www.bootcdn.cn/jquery/ ...

  3. 代码管理平台之git

    yum install -y gitmkdir -p /date/gitrootcd !$git init git add 1.txtgit commit -m "add 1.txt&quo ...

  4. java 读取 yaml 文件

        做 java 项目用的最多的配置文件就是 properites 或者 xml, xml 确实是被用烂了,Struts, Spring, Hibernate(ssh) 无一不用到 xml.相比厚 ...

  5. Java程序员月薪三万,需要技术达到什么水平?

    最近跟朋友在一起聚会的时候,提了一个问题,说 Java 程序员如何能月薪达到二万,技术水平需要达到什么程度?人回答说这只能是大企业或者互联网企业工程师才能拿到.也许是的,小公司或者非互联网企业拿二万的 ...

  6. 简单了解css3轮廓outline

    outline属性是用来设置一个或多个单独的轮廓属性的简写属性 , 例如 . 轮廓有下面几个属性: { outline-style: solid; outline-width: 10px; outli ...

  7. 记录开发基于百度地图API实现在地图上绘制轨迹并拾取轨迹对应经纬度的工具说明

    前言: 最近一直在做数据可视化方面的工作,其中平面可视化没什么难度,毕竟已经有很多成熟的可供使用的框架,比如百度的echart.js,highcharts.js等.还有就是3D可视化了,整体来说难度也 ...

  8. python 调试大法

    说在前面 我觉得没有什么错误是调试器无法解决的,如果没有,那我再说一遍,如果有,那当我没说 一.抛出异常 可以通过 raise 语句抛出异常,使程序在我们已经知道的缺陷处停下,并进入到 except ...

  9. django中使用原生的sql查询实例

    在app文件夹下创建database_operations.py文件,写如下内容: import pymysql from 项目名.settings import DATABASES class Da ...

  10. Oracle 分页 ROWNUM 两种分页方法和ROWID用法

    一 原因一 oracle默认为每个表生成rowmun,rowid字段,这些字段我们称之为伪列 测试表 CREATE TABLE A ( AID NUMBER() primary key, ANAME ...