黑马程序员:Java基础总结



反射

 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!




反射


反射的基石:Class类

Class类代表Java类,它的各个实例对象又分别对应什么呢?
对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?
如何得到各个字节码对应的实例对象( Class类型)
类名.class,例如,System.class
对象.getClass(),例如,new Date().getClass()
Class<?> getClass()
          返回此 Object 的运行时类。

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

static Class<?> forName(String className)
          返回与带有给定字符串名的类或接口相关联的 Class 对象。

九个预定义Class实例对象:
参看Class.isPrimitive方法的帮助
Int.class == Integer.TYPE
 boolean isPrimitive()
          判定指定的 Class 对象是否表示一个基本类型。

数组类型的Class实例对象
Class.isArray()
 boolean isArray()
          判定此 Class 对象是否表示一个数组类。

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…



反射概念

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

表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。 


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

Class类中的方法
 Constructor<T> getConstructor(Class<?>... parameterTypes)
          返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
 Constructor<?>[] getConstructors()
          返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
得到某个类所有的构造方法:
例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
例子: Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);  //获得方法时要用到类型
             Constructor con = Class.forName("java.lang.String").getConstructor(
                         int.class );

java.lang.reflect.Constructor类中的方法

创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));  //调用获得的方法时要用到上面相同类型的实例对象

T newInstance(Object... initargs)
          使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
            String str = (String) con.newInstance( new StringBuffer("qwrt" ));

Class.newInstance()方法:
 T newInstance()
          创建此 Class 对象所表示的类的一个新实例。

例子:String obj = (String)Class.forName("java.lang.String").newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。



Field类:代表某个类中的一个成员变量

Class类中的方法
 Field getField(String name)
          返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定[公共public]成员字段。
 Field[] getFields()
          返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。
Field y = fi.getClass().getField(
"a"
);
java.lang.reflect.Field中的方法
Object get(Object obj)
          返回指定对象上此 Field 表示的字段的值。
System.
out
.println(fa.get(fi));

访问非公有成员
 Field getDeclaredField(String name)
          返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
 Field[] getDeclaredFields()
          返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

 void setAccessible(boolean flag)
          将此对象的 accessible 标志设置为指示的布尔值。

            Fie fi = 
new 
Fie(2, 3);
            Field fa = fi.getClass().getDeclaredField( 
"a"
);
            fa.setAccessible( 
true
);
            System. 
out
.println(fa.get(fi));

高级用法:问题:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
 void set(Object obj, Object value)
          将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
public 
class 
Ts0 {

       
public 
static 
void 
main(String[] args) 
throws 
Exception {
            Text text = 
new 
Text();
            Field[] fields = text.getClass().getFields();
             
for 
(Field field : fields) {
                   
// if(field.getType().equals(String.class)){
                   
if 
(field.getType() == String.
class
) {
                        String oldVar = (String) field.get( text);
                        String newVar = oldVar.replace( 
'a'

'1' 
);
                        field.set( text, newVar);
                  }
            }
            System. 
out
.println(text);
      }

}

class 
Text {
       
public 
String 


"jfaiweonv"
;
       
public 
String 


"fewiojavo"
;
       
public 
String 


"fejwaofkpwel"
;

       
@Override
       
public 
String toString() {
             
return 


":" 



":" 


;
      }
}


Method类代表某个类中的一个成员方法

Class类中的方法
 Method getMethod(String name, Class<?>... parameterTypes)
          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
 Method[] getMethods()
          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method method = Class. forName
"java.lang.String" 
).getMethod(
 "substring"

int 
.
 class

int
 .
 class
);
java.lang.reflect.Method类中的方法
Object invoke(Object obj, Object... args)
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
参数:
obj - 从中调用底层方法的对象    
args - 用于方法调用的参数
如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。
如果底层方法
所需的形参数为 0,则所提供的 
args 数组长度可以为 0 或 null。
            Method method = Class.forName(
 "java.lang.String"
).getMethod( 
"substring"
 , 
int 
.
 class

int
 .
class 
);
            String a =(String) method.invoke( 
new
 String(
"abcdefg" 
), 1,3);
            System. 
out
 .println(a);

用反射方式执行某个类中的main方法
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。用普通方式调完后,大家要明白为什么要用反射方式去调啊?

             Class clazz = Class.forName(args[0]);
            Method method = clazz.getMethod(
"main"
, String[]. 
class
);
            method.invoke( 
null
, (Object) 
new 
String[] { 
"123"

"456"

"789" 
});

数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象(此处比较与值无关)。
如:int [][] a = new int [1][3];   int [][] b = new int [1][3];   a.getclass()==b.getclass
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

Arrays.asList()方法处理int[]和String[]时的差异。
             
int
[] a = { 1, 2, 3, 4, 5 };
            String[] b = { 
"a"

"b" 

"c" 

"d" 

"e" 
};
            System. 
out
.println(Arrays.asList(a)); 
//[[I@34780af5]
            System. 
out
.println(Arrays.asList(b)); 
//[a, b, c, d, e]

java.lang.reflect.Array:工具类用于完成对数组的反射操作。
static Object get(Object array, int index)
          返回指定数组对象中索引组件的值。
static int getLength(Object array)
          以 int 形式返回指定数组对象的长度。
static void set(Object array, int index, Object value)
          将指定数组对象中索引组件的值设置为指定的新值。

            String[] b = { 
"a"

"b"

"c" 

"d" 

"e" 
};
             
if 
(b.getClass().isArray()) {
                  System. 
out
.println(Array.getLength( b));
                  Array. set(b , 1, 
"1" 
);
                  System. 
out
.println(Arrays.asList( b));
            }

反射的作用:实现框架功能

什么是框架,例如,我们要写程序扫描.java文件中的注解,要解决哪些问题:读取每一样,在每一个中查找@,找到的@再去查询一个列表,如果@后的内容出现在了列表中,就说明这是一个我能处理和想处理的注解,否则,就说明它不是一个注解或者说至少不是一个我感兴趣和能处理的注解。接着就编写处理这个注解的相关代码。现在sun提供了一个apt框架,它会完成所有前期工作,只需要我们提供能够处理的注解列表,以及处理这些注解的代码。Apt框找到我们感兴趣的注解后通知或调用我们的处理代码去处理。

你做的门调用锁,锁是工具,你做的门被房子调用,房子是框架,房子和锁都是别人提供的。

import 
java.io.InputStream;
import 
java.util.Collection;
import 
java.util.Properties;

public 
class 
Ts {
       
public 
static 
void 
main(String[] args) 
throws 
Exception {
             
// 应该先直接用ArrayList和HashSet,然后才引入从配置文件读,这样便于学员学习。
            Properties props = 
new 
Properties();
            
// 先演示相对路径的问题
     
          完整路径:Jsp中
                              /*getRealPath();//金山词霸/内部          !一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。*/

     
          相对路径:
Class类也提供getResourceAsStream
ClassLoader getClassLoader()
          返回该类的类加载器。
 InputStream getResourceAsStream(String name)
          查找具有给定名称的资源。

             
// InputStream ips = new FileInputStream("config.properties");
             
/*
             * 一个类加载器能加载.class文件,那它当然也能加载 classpath环境下的其他文件,既然它有如此能力,它没有理由不顺带提供这样一个方法。
             * 它也只能加载 classpath环境下的那些文件。注意:直接使用类加载器时,不能以/打头。
             */
             
// InputStream ips =
             
// ReflectTest2.class.getClassLoader().getResourceAsStream("cn/ itcast/javaenhance /config.properties");
               IDE会把src中所有的非.java的文件自动搬到bin中,所以相对路径没问题,推荐使用
             
// Class提供了一个便利方法,用加载当前类的那个类加载器去加载相同包目录下的文件
             
// InputStream ips =
             
// ReflectTest2.class.getResourceAsStream("config.properties");
            InputStream ips = Ts.
class
.getResourceAsStream(
"temp.properties" 
);
            props.load(ips);
            ips.close();

            String className = props.getProperty( 
"className"
);
             Class clazz = Class.forName(className);

             Collection collection = (Collection) clazz.newInstance();
             
// Collection collection = new ArrayList();
             collection.add(1);
            System. 
out
.println(collection.size());
      }
}






 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!

黑马程序员:Java基础总结----反射的更多相关文章

  1. 黑马程序员——JAVA基础之反射

      ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! -------     Java 反射是Java语言的一个很重要的特征,它使得Java具体了"动态 ...

  2. 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  3. 黑马程序员_Java基础:反射机制(Reflection)总结

    ------- android培训.java培训.期待与您交流! ---------- 反射在java中有非常重大的意义,它是一种动态的相关机制,可以于运行时加载.探知.使用编译期间完全未知的clas ...

  4. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  5. 黑马程序员----java基础笔记上(毕向东)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...

  6. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  7. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  8. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  9. 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流

    ------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...

  10. 黑马程序员——JAVA基础之多线程的安全问题

    ------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...

随机推荐

  1. 原生js写的一个弧形菜单插件

    弧形菜单是一种半弧式或者全弧形菜单,是一种不同于传统横向或者竖向菜单形式的菜单.最近在网上看到好多人写出了这种效果,于是也尝试自己写了一个. 实现方式:原生态js 主要结构: 1.参数合并 var d ...

  2. 让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的任务管理器的性能面板,显示磁盘数据

    运行[diskperf -y],关闭任务管理器,重新打开即可.

  3. Invent 2014回顾

    AWS re:Invent 2014回顾   亚马逊在2014年11月11-14日的拉斯维加斯举行了一年一度的re:Invent大会.在今年的大会上,亚马逊一股脑发布和更新了很多服务.现在就由我来带领 ...

  4. MVC 用扩展方法执行自定义视图,替代 UIHint

    MVC 用扩展方法执行自定义视图,替代 UIHint 项目中用了 Bootstrap , 这样就不用写太多的CSS了,省去很多事情.但是这个业务系统需要输入的地方很多,每个表都有100多个字段,每个页 ...

  5. 构建具有深度和灵活性的安卓Wear应用

    自从去年Android 5.0发布以后就一直在关注可穿戴方面的事情.这个年的前后一直在忖度该怎么海淘一个moto 360,可是考虑到iWatch在本年度四月份发布,估计现在已经有的Android可穿戴 ...

  6. Bootstrap 网格系统

    自版本 2.3.2 起,Bootstrap 提供了两种类型的网格,默认网格系统和流动网格系统.默认的网格系统是 940px 宽和 12 列.本文主要讲解第一种. 首先让我们看,怎么来应用默认网格系统 ...

  7. 安装dynamics CRM 2013提示“实例名称必须与计算机名称相同”

    在安装CRM 2013的时候,最后一步一直提示“实例名称必须与计算机名称相同”. 原因是在安装数据库之后,我更改了计算机名称.因此就导致了可这个错. 在安装数据库的时候,数据库会记住计算机的名称,用 ...

  8. worker进程中线程的分类及用途

    worker进程中线程的分类及用途 欢迎转载,转载请注明出版,徽沪一郎. 本文重点分析storm的worker进程在正常启动之后有哪些类型的线程,针对每种类型的线程,剖析其用途及消息的接收与发送流程. ...

  9. 用Haproxy给MySQL做负载均衡

    1.安装 # wget http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.24.tar.gz # tar zcvf haproxy-1.4.24.t ...

  10. win7 64位iis发生错误w3wp.exe解决方法

    服务器为64的,遇到iis错误w3wp.exe 于是百度,网上说的修改iis权限和修改注册表都不行,后来在msdn上找到解决方法,如下所示 设置iis程序集如下即可