`
把阳光剪成雨Java
  • 浏览: 25201 次
  • 性别: Icon_minigender_1
  • 来自: 长春
社区版块
存档分类
最新评论

黑马程序员——反射

 
阅读更多

----------------- android培训java培训、期待与您交流! -----------------
 

 

 

反射

1.  Class

平常的java类是通过一些固定的支架(方法,成员变量等)搭建来的,搭建完成后它就具备了描述一类事物的特性。

而这些支架也属于事物,它也能够被类描述。所以java中就提供了Class类进行描述。

Class类所描述的事物是:java类在编译完成后,会生成class文件存在硬盘上。也就是

字节码。把字节码(保存了该类的基本信息)加载到内存中来。返回的类型是Class,当然

Class就具备了描述该类固定支架(方法,成员变量等)的特性。得到字节码的方法3种:

类名.class  例如,System.class

对象.getClass() 例如,new Date().getClass();

Class.forName(),例如,Class.forName("java.util.Date");

1,如果字节码已经在内存中,直接拿过来就哦了。

2,如果字节码不在内存中,需要从硬盘上把字节码加载到内存中去。

2.  分析Class类。

package reflect;

public class ReflectTest {

    public static void main(String[] args) throws ClassNotFoundException {

 

       String abc = "afd";

       Class cls1 = abc.getClass();

       Class cls2 = String.class;

       Class cls3 = Class.forName("java.lang.String");

       // 虚拟机上做出该类一份字节码,其他要用就直接拿了。所以打印结果都为true

       System.out.println(cls1 == cls2);

       System.out.println(cls1 == cls3);

 

       // 判断是否是基本数据类型的字节码isPrimitive()false

       System.out.println(cls1.isPrimitive());

       // 基本类型的字节码和对应的封装类的字节码是不相同的。false

       System.out.println(int.class == Integer.class);

       // TYPE常量代表包装类型所包装的基本类型的字节码。true

       System.out.println(int.class == Integer.TYPE);

       // 数组的字节码类型,不是原始类型false

       System.out.println(int[].class.isPrimitive());

       // 数组的字节码类型,判断一个Class类型是否为数组用isArray()true

       System.out.println(int[].class.isArray());

 

      

       // Class类型,判断基本数据类型:isPrimitive();判断数组类型:isArray();

       // 总之:只要是在源程序中出的类型,都有各自的Class

    }

 

}

 

 

3.  反射的概念。

反射就是把Java类中的各种成分映射成相应的java类。

4.  Constructor

Constructor类代表某个类中的一个构造方法。

//得到构造方法:    通过构造函数参数列表的类型,来确定获取的具体构造类。

       Constructor<String> strCon = String.class.getConstructor(StringBuffer.class);

//     new String(new StringBuffer("abc"));

//创建实例对象:

//     1,在对strCon进行实例化对象的时候,需要指定参数对象。

       String str2 = strCon.newInstance(new StringBuffer("abc"));

       System.out.println(str2.charAt(2));

//     2,Class类提供了一个便利,有newInstance方法。直接可以创建对象。省去了获取Constructor再去创建对象。

//     反射的缺点:反射比较消耗性能占用时间,进行反射以后把得出的结果存在缓存起来。为后面尽可能的减少反射的使用量。

       String s = String.class.newInstance();

    }

 

5.  Field

 

package reflect;

 

import java.lang.reflect.Field;

 

public class FieldDemo {

    public static void main(String[] args) throws SecurityException, NoSuchFieldException, InstantiationException, IllegalAccessException {

       ReflectPoint p = new ReflectPoint(3,5);

//     字段通过字段名字区分。它不代表某个特定对象上面的值。而是告诉程序员,这个叫y的变量已经给你取到了。封装成了一个类。

//     类上的变量,不是对象上的变量。不包括私有的。

       Field fieldY = p.getClass().getField("y");

//     从特定对象上取值。这个异常说明了,成员是私有的不让访问。

//     Exception in thread "main" java.lang.NoSuchFieldException: y

//     at java.lang.Class.getField(Class.java:1520)

//     at reflect.FieldDemo.main(FieldDemo.java:10)

 

       System.out.println(fieldY.get(p));

//     获取所有申明的变量。包括private类型。

       Field fieldX = p.getClass().getDeclaredField("x");

//  java.lang.IllegalAccessException: Class reflect.FieldDemo can not access a member of class reflect.ReflectPoint with modifiers "private"

//     上面异常的出现说明了,没有获取私有变量值的权限。

//     如果想要获取的话,需要进行暴力反射。

       fieldX.setAccessible(true);

       System.out.println(fieldX.get(p));

//     Class c = String.class;

//     String s = (String) c.newInstance();

//    

//     String s1 = String.class.newInstance();

    }

}

将一个对象上所有的String类型的值中含有a的,进行替换。

    private static void changeValue(ReflectPoint p) throws IllegalArgumentException, IllegalAccessException {

//  获取ReflectPoint中所有申明的字段。

       Field[] fs = p.getClass().getDeclaredFields();

//     遍历字段。

       for(Field f:fs){

//         getType获取Field的类型,用==好,因为字节码只有一份。如果是String类型的话,就进行操作。

           if(f.getType()==String.class){

              String oldValue = (String)f.get(p);

              String newValue = oldValue.replace("b", "a");

              f.set(p,newValue);

              System.out.println(newValue);

           }

       }

    }

}

反射的作用:你给我一个对象我能把他里面的值都改掉。例如Spring框架中用的就是这个技术。你给我一个类,我就能用你给的资源来做些事情。。

6.  Method

 

//  通过方法名字,和参数列表来确定方法。导包的时候看到com...这种包是内部用的(不要导),看到java...这就是外部用的。

       String str = "abc";

       Method methodCharAt = String.class.getMethod("charAt", int.class);

      

//     已知Method,调用谁的Method并且还要给它传参数。

       Character ch = (Character) methodCharAt.invoke(str, 2);

       System.out.println(ch);

//     静态方法的调用,因为静态方法不需要对象。第一个参数应该是null。所以:

//      Character ch2 = (Character) methodCharAt.invoke(null, 2);

      

       String className= args[0];

       invokeMain(className);

    }

//  专家模式:只要类中有这个私有的数据,对这个数据的操作只能是我这个类的方法。

//  谁享有数据,谁就对这个数据有操作的权利。

 

 

7.  调用其他类的main方法。

为什么要用反射的方式调用main

main的参数是String数组,数组里面可以装类名字符串。

获取这这些类的名字。通过反射的原理可以获得各个类中的main方法。

分别执行这几个类。

    private static void invokeMain(String className) throws Exception {

       Method main = Class.forName(className).getMethod("main", String[].class);

//     main是静态,所以第一个参数是空的。

//  java.lang.IllegalArgumentException: wrong number of arguments jdk1.4特点,给进去一个数组会将数组拆掉,拆掉后的值作为参数造成的。导致参数变多了。

       main.invoke(null, new Object[]{new String[]{"1","2","3"}});

//     main.invoke(null, (Object)new String[]{"1","2","3"});

}

 

8.  数组的反射。

package reflect;

import java.lang.reflect.Array;

import java.util.Arrays;

 

public class ArrayReflectDemo {

    public static void main(String[] args) {

       int[] a = new int[3];

       int[] a2 = new int[4];

       int[][] a3 = new int[2][3];

       String[] a4 = new String[3];

       // 数组class是否相同:1.数据类型2数组的维数

       System.out.println(a.getClass() == a2.getClass());

       // 数组的父类是Object

       System.out.println(a4.getClass().getSuperclass().getName());

       // 

       Object aObj1 = a;

       Object aObj2 = a2;

       // 因为a是一维数组,里面装的是int型变量,不是Object子类。不行。

       // Object[] obj1=a;

       // 二维数组,数组里面套数组。内层数组(一维数组)相当于是Object。可以

       Object[] aobj3 = a3;

       // String数组里面装的是String类型的变量。可以

       Object[] aobj4 = a4;

       System.out.println(Arrays.asList(a));

       System.out.println(Arrays.asList(a4));

//     数组的反射。

      

       printObjcet(a4);

    }

 

    private static void printObjcet(Object obj) {

       Class clazz = obj.getClass();

       if(clazz.isArray()){

//         反射

           int len = Array.getLength(obj);

           for(int i=0;i<len;i++){

              System.out.println(Array.get(obj, i));

           }

       }

    }

}

 

 

 

 

分享到:
评论

相关推荐

    黑马程序员——Android移动开发源码

    黑马程序员——Android移动开发源码

    黑马程序员——赢在习惯

    NULL 博文链接:https://xianglachigen.iteye.com/blog/1564376

    C++黑马程序员学习资料

    C++黑马程序员学习资料,附赠《InterviewGuide第四版By阿秀》、《LeetCode刷题手册》、《背包问题九讲》、《算法图解》pdf版本,三个基础课程文档手册及三个实验项目,由简到繁分别为《通讯录管理系统》、《职工管理...

    黑马程序员入学Java知识——精华总结

    黑马程序员入学Java知识——精华总结

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--aidl之结合反射获取应用缓存大小等空间占用 |--aidl调用系统service未公开的方法挂电话 |--aidl调用系统未公开的方法代码示例2 |--android dp和px之间转换 |--android INSTALL_PARSE_FAILED_MANIFEST_MALFORMED |...

    教材源码_javaweb_黑马程序员Javaweb源码_

    黑马程序员是一家知名的IT教育机构,他们提供的Javaweb教材源码是为了帮助学员深入理解和实践Web开发技术。下面将详细介绍JavaWeb的基本概念、核心技术和黑马程序员源码在学习过程中的作用。 1. **JavaWeb基础** ...

    黑马程序员Javase笔记

    "黑马程序员Javase笔记"是一个自学者在学习黑马程序员提供的Java全套课程过程中整理的笔记,主要涵盖了Java Standard Edition (Javase) 的核心内容。下面将详细讨论其中的关键知识点。 首先,DOS命令是操作系统中的...

    黑马程序员 C语言提高课程配套课件

    黑马程序员 C语言提高课程配套课件 黑马程序员 C语言提高课程配套课件

    黑马程序员测试题部分答案

    【标题】:“黑马程序员测试题部分答案”涵盖了在学习编程过程中可能会遇到的各类测试题目及其解答,主要由“黑马程序员”这个知名的IT教育机构的教学资源衍生而来。这些测试题目的答案,旨在帮助学习者检验自己的...

    传智播客旗下黑马程序员c++视频课程内部讲义

    传智播客旗下黑马程序员c++视频课程内部讲义 就是上课时老师翻阅的那个讲义

    黑马程序员,C++核心编程

    黑马程序员,C++核心编程

    黑马程序员 大事件案例程序

    layui ajax 没有node.js功能都可用,高度类似。 黑马刘龙彬老师主讲的大事件项目,整体看完,给...最后,再次给黑马程序员和刘老师点个赞。 说明--ShowDoc https://www.showdoc.com.cn/escook?page_id=3707158761215217

    黑马程序员毕业设计资料,代码,数据库设计论文等

    "黑马程序员网上图书商城中的毕业设计资料,代码,数据库设计论文等" 描述进一步细化了这些资源的来源——黑马程序员的网上图书商城,暗示这可能是一个基于在线书店的系统设计项目。资源不仅限于理论知识,还有实际...

    B站黑马程序员Python教程学习笔记.zip

    在B站黑马程序员的Python教程中,你将深入理解Python的基础概念,包括: 1. **变量与数据类型**:Python支持多种数据类型,如整型(int)、浮点型(float)、字符串(str)和布尔型(bool)。此外,还有列表(list...

    黑马程序员ssm代码分享

    内容概要:通过带着读者手写简化版 Spring 框架了解 Spring 核心原理。在手写Spring源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程保留核心功能, ...本代码基于黑马程序员的课程,最好根据课程同步学习

    黑马程序员Vue深入浅出视频代码

    这是根据黑马程序员中关于Vue11天课程中,跟着视频编写的代码,一行行跟着写出来的,连备注基本也是和视频一样,用的是vscode开发工具,上传的资料已经把node_modules删除了,进入目录后,用cnpm i重新安装一下就...

    Netty基础,用于学习Netty,参考黑马程序员的netty教程

    Netty基础,用于学习Netty,参考黑马程序员的netty教程

    黑马程序员JAVA WEB全笔记pdf

    本笔记基于黑马程序员的课程内容,全面覆盖了Java Web的基础知识,包括前端开发技术如HTML、CSS、JavaScript,以及后端服务器端的Java Servlet和JSP(Java Server Pages)。 一、前端基础 1. ...

    Java Web程序设计任务教程源码(黑马程序员)

    《Java Web程序设计任务教程》是一本专注于Java Web开发实践的书籍,由中国工信出版社出版,由传智播客旗下的高端教育品牌“黑马程序员”精心编著。这本书旨在帮助读者掌握Java Web开发的核心技术和实践方法,通过一...

    黑马程序员JavaEE49期

    黑马程序员JavaEE49期

Global site tag (gtag.js) - Google Analytics