黑马程序员——JAVA基础之反射
反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象
2、实例化对象,获得类的属性、方法或构造函数
3、访问属性、调用方法、调用构造函数创建对象
class类:
所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class。Class类中就包含属性有field(字段)、method(方法)、construction(构造函数)。
Class和class区别:
1、class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。
2、Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。
获取Class对象,有三种方式:
1、通过每个对象都具备的方法getClass来获取,弊端:必须要创建该类对象,才可以调用getClass方法
2、每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class,弊端:必须要先明确该类
前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成
3、使用的Class类中的方法,静态的forName方法
指定什么类名,就获取什么类字节码文件对象,这种方式的扩展性最强,只要将类名的字符串传入即可
- //根据给定的类名来获得 用于类加载
- String classname ="cn.itcast.reflect.Person";// 来自配置文件
- Class clazz =Class.forName(classname);// 此对象代表Person.class
- //如果拿到了对象,不知道是什么类型 用于获得对象的类型
- Object obj = new Person();
- Class clazz1 =obj.getClass();// 获得对象具体的类型
- //如果是明确地获得某个类的Class对象 主要用于传参
- Class clazz2 = Person.class;
Class类中常用的方法:
static Class forName(String className):1、返回与给定字符串名的类或接口的相关联的Class对象。
Class getClass():返回的是Object运行时的类,即返回Class对象即字节码对象
Constructor getConstructor():返回Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。
Field getField(String name):返回一个Field对象,它表示此Class对象所代表的类或接口的指定公共成员字段。
Field[] getFields():返回包含某些Field对象的数组,表示所代表类中的成员字段。
Method getMethod(String name,Class… parameterTypes):返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。
Method[] getMehtods():返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。
String getName():以String形式返回此Class对象所表示的实体名称。
String getSuperclass():返回此Class所表示的类的超类的名称
boolean isArray():判定此Class对象是否表示一个数组
boolean isPrimitive():判断指定的Class对象是否是一个基本类型。
T newInstance():创建此Class对象所表示的类的一个新实例。
- class Person {
- private String name;
- public int age;
- public Person(){
- System.out.println("Person run");
- }
- public Person(String name,int age){
- this.age = age;
- this.name = name;
- }
- public String toString(){
- return name+":"+age;
- }
- }
- public class ClassDemo{
- public static void main(String[] args) throws Exception {
- // 获取类的全名称字符串
- String className = "cn.itheima.Person";
- // 获取Person类的Class对象
- Class clazz = Class.forName(className);
- // 通过newInstance方法获取类的无参构造函数实例
- Person p = (Person)clazz.newInstance();
- }
- }
Constructor类
Constructor代表某个类的一个构造方法。
Constructor构造方法
1、得到这个类的所有构造方法: Constructor[] cons = Class.forName (“java.lang.String”) . getConstructors ();
2、得到某一个构造方法: Constructor con = String.class.getConstructor (String.class , int.class);
创建实例对象
通常方式:String str = new String ( new StringBuffer(“abc”));
反射方式:String str = (String) constructor.newInstance ( new StringBuffer (“abc”));
注:
(1)创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。
(2)newInstance():构造出一个实例对象,每调用一次就构造一个对象。
(3)利用Constructor类来创建类实例的好处是可以指定构造函数,而Class类只能利用无参构造函数创建类实例对象。
- class Person {
- private String name;
- public int age;
- public Person(){
- System.out.println("Person run");
- }
- public Person(String name,int age){
- this.age = age;
- this.name = name;
- }
- public String toString(){
- return name+":"+age;
- }
- }
- //通过Constructor对象来创建类实例方法
- public static void ConstructorDemo() throws Exception{
- //获取Person类的Class对象
- String name = "cn.itheima.Person";
- Class clazz = Class.forName (name);
- //Class clazz = Person.class;
- //获取指定构造函数的类实例
- Constructor con = clazz.getConstructor (String.class , int.class);
- Person p = (Person) con.newInstance("lisi",30);
- System.out.println (p.toString());
- }
Field方法
1、Field getField(String s):只能获取公有和父类中公有
2、Field getDeclaredField(String s):获取该类中任意成员变量,包括私有
3、setAccessible(ture)://如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
4、set(Object obj, Object value):将指定对象变量上此Field对象表示的字段设置为指定的新值。
5、Object get(Object obj):返回指定对象上Field表示的字段的值。
- class Person {
- private String name;
- public int age;
- public Person(){
- System.out.println("Person run");
- }
- public Person(String name,int age){
- this.age = age;
- this.name = name;
- }
- public String toString(){
- return name+":"+age;
- }
- }
- //获取Person对象的成员变量
- public static void getPersonField() throws Exception{
- //如果想要给该变量赋值,必须先要有对象。
- Class clazz = Class.forName("cn.itheima.Person");
- Person p = (Person)clazz.newInstance();
- //获取所有的成员变量
- Field[] fs = clazz.getFields();
- for(Field f:fs){
- System.out.println(f);
- }
- //获取指定的成员变量
- Field fage = clazz.getField("age");
- Field fname = clazz.getDeclaredField("name");
- //显示改变后的值
- fage.set(p, 20);
- System.out.println(fage.get(p));
- //暴力访问私有变量
- fname.setAccessible(true);
- fname.set(p, "zhangsan");
- System.out.println(fname.get(p));
- }
Method类代表某个类中成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
Method方法
Method[] getMethods():只获取公共和父类中的方法。
Method[] getDeclaredMethods():获取本类中包含私有。
Method getMethod("方法名",参数.class(如果是空参可以写null));
Object invoke(Object obj ,参数):调用方法
注:① invoke方法:如果底层是静态的,那么可以忽略指定的obj参数,填充为null。② 如果底层方法所需的“形式参数”为0,则所提供的args数组长度可以为0或null。
获取类中方法
1、通常方式:对象名.函数。如str.charAt(int index);
2、反射方式:
Method MethodCharAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
3、反射调用底层方法:charAtMethod.invoke(str, int index);
说明:如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法
- class Person {
- private String name;
- public int age;
- public Person(){
- System.out.println("Person run");
- }
- public Person(String name,int age){
- this.age = age;
- this.name = name;
- }
- public String toString(){
- return name+":"+age;
- }
- }
- public static void getPersonMethod() throws Exception{
- //如果想要获取方法,必须先要有对象。
- Class clazz = Class.forName("cn.itheima.Person");
- //获取所有方法
- Method[] methods = clazz.getMethods();//只获取公共的和父类中的。
- //methods = clazz.getDeclaredMethods();//获取本类中所有的方法,包含私有。
- for(Method method : methods){
- System.out.println(method);
- }
- //获取单个方法
- Method me=clazz.getMethod("toString", null);
- Object returnVaule=me.invoke(p, null);
- System.out.println(returnVaule);
- }
具有相同维数和元素类型的数组属于同一个类型,具有相同的Class实例对象。数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
如何得到某个数组中的某个元素的类型?
例如:Object[] obj=new Object[]{“ABC”,1};无法得到某个数组的具体类型,只能得到其中某个元素的类型,如:Obj[0].getClass().getName() 得到的是java.lang.String。
Arrays.asList()方法,在处理int[]是String[]时,是不同的。它会将int[]整体作为一个对象元素存入list集合。而会将String[]数组中的每一个字符串元素当做对象存入list集合。
Array工具类(java.lang.reflect.Array)用于完成对数组的反射操作,它提供了动态创建和访问Java数组的方法:如
Array.getLength(Object obj);//获取数组的长度
Array.get(Object obj,int x);//获取数组中的元素
- import java.lang.reflect.Array;
- import java.util.Arrays;
- public class ArrayReflect {
- public static void main(String[] args) {
- int [] a1 = new int[]{1,2,3};
- int[][] a2 = new int[2][3];
- String [] a3 = new String[]{"a","b","c"};
- Object obj1 = a1;
- Object obj2 = a3;
- Object obj3 = a4;
- //Array工具类用于完成对数组的反射操作。如打印任意数值
- printObject(a1);
- printObject(a4);
- printObject("abc");
- }
- //打印任意数值
- private static void printObject(Object obj) {
- Class clazz = obj.getClass();
- //如果传入的是数组,则遍历
- if(clazz.isArray()){
- int len = Array.getLength(obj);//Array工具类获取数组长度方法
- for(int x = 0;x<len;x++){
- System.out.println(Array.get(obj, x));//Array工具获取数组元素
- }
- }
- else
- System.out.println(obj);
- }
- }
框架要解决的核心问题
我们在写框架的时候,调用的类还未出现,那么框架无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象,而要通过反射来做。
简单框架的创建步骤:
1、创建一个配置文件,在Eclipse的java项目面板中:
“右键”——“New”——选择“File“,file name命名为config.properties,然后写入配置信息。如className=java.util.ArrayList,等号右边是配置键,右边是值。
2、代码实现,加载此文件:
① 将文件读取到读取流中,要写出配置文件的路径(相对路径或绝对路径)。如:InputStream ips = new FileInputStream(“config.properties”);
② 用Properties类的load()方法将流中的数据装载入集合。
③ 关闭流资源:关闭的是读取流,因为流中的数据已经加载进内存。
3、通过getProperty()方法获取className,即配置的值,也就是某个类名。
4、用反射的方式,创建对象newInstance()。
5、执行程序主体功能
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员——JAVA基础之反射的更多相关文章
- 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)
正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G QQ 1481135711 这是我总 ...
- 黑马程序员_Java基础:反射机制(Reflection)总结
------- android培训.java培训.期待与您交流! ---------- 反射在java中有非常重大的意义,它是一种动态的相关机制,可以于运行时加载.探知.使用编译期间完全未知的clas ...
- 黑马程序员----java基础笔记中(毕向东)
<p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...
- 黑马程序员----java基础笔记上(毕向东)
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...
- 黑马程序员——JAVA基础之泛型和通配符
------- android培训.java培训.期待与您交流! ---------- 泛型: JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...
- 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象
------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...
- 黑马程序员——JAVA基础之语法、命名规则
------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...
- 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流
------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...
- 黑马程序员——JAVA基础之多线程的安全问题
------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...
随机推荐
- shiro 简单的身份验证 案例
Apache Shiro是Java的一个安全框架,Shiro可以帮助我们完成:认证.授权.加密.会话管理.与Web集成.缓存等. 简单的身份验证 项目目录: 首先,在shiro.ini里配置了用户名和 ...
- win7 windows server 2008R2下 https SSL证书安装的搭配(搭配https ssl本地测试环境)
原文:http://www.cnblogs.com/naniannayue/archive/2012/11/19/2776948.html 要想成功架设SSL安全站点关键要具备以下几个条件. 1.需要 ...
- python3 对文件的查找、替换、删除
python 版本 3.5 实现对文件的查找,替换,删除 #Author by Andy #_*_ coding:utf-8 _*_ #定义查找函数 def find(): Keywords=inpu ...
- null 和 undefined 的区别
null表示"没有对象",即该处不应该有值. (1) 作为函数的参数,表示该函数的参数不是对象. (2) 作为对象原型链的终点. undefiend 就是一个缺少值,此处应该有的值 ...
- 饮水思源——python中常用基础类源码解析
1.bool类 2.int类 3.long类 4.float类 5.str类 6.list类 7.tuple类 8.dict类 9.collections类 Counter类:为hashable对象计 ...
- C++数组小知识
数组大小 我们一般情况下可以使用sizeof(数组名)/sizeof(数组元素)求数组元素个数,但需要注意的是,当我们需要调用函数处理数组时,数组的长度要在调用函数之前获取,因为调用函数的时候,数组退 ...
- svn用法:摘自http://wh-vip-126-com200907043220.iteye.com/blog/424642
下载最新版本svn(http://www.visualsvn.com/server/ ) 1.安装SVN 2.创建user与repository 3.Eclipse下配置SVN插件 3.1帮助- ...
- iOS开发UI篇—Quartz2D使用(图片剪切)
iOS开发UI篇—Quartz2D使用(图片剪切) 一.使用Quartz2D完成图片剪切 1.把图片显示在自定义的view中 先把图片绘制到view上.按照原始大小,把图片绘制到一个点上. 代码: - ...
- Halcon 10.0 Sample:完整性检查(圆形)
* ball.hdev: Inspection of Ball Bonding * 球接合检查 Comment Time:// *核心思想:.白色区域用作自动ROI,黑色区域是目标 * .Openin ...
- erlang中的lists:foldl()的用法,格式转换实例应用
lists:foldl(fun(),参数1,参数2):这个函数就是先把参数1传给fun()处理,然后将参数2(列表)中每一个元素,依次传给fun()函数进行处理. lists:foldl(fun(El ...