黑马程序员: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. Modernizr

    Modernizr 目录 概述 CSS的新增class JavaScript侦测 加载器 参考链接 概述 随着HTML5和CSS3加入越来越多的模块,检查各种浏览器是否支持这些模块,成了一大难题.Mo ...

  2. UiAutomator源码分析之获取控件信息

    根据上一篇文章<UiAutomator源码分析之注入事件>开始时提到的计划,这一篇文章我们要分析的是第二点: 如何获取控件信息 我们在测试脚本中初始化一个UiObject的时候通常是像以下 ...

  3. userAgent,JS这么屌的用户代理,你造吗?——判断浏览器内核、浏览器、浏览器平台、windows操作系统版本、移动设备、游戏系统

    1.识别浏览器呈现引擎 为了不在全局作用域中添加多余变量,这里使用单例模式(什么是单例模式?)来封装检测脚本.检测脚本的基本代码如下所示: var client = function() { var ...

  4. Mvc 导出 Excel

    Mvc 导出 Excel 之前接触过Webform,winfrom 的导出Excel方法 ,优点:省事.缺点:服务器必须安装Office 这几天做项目 和 大牛学习了一下 新的方法,自己加以总结.希望 ...

  5. 转载:Linux Used内存到底到哪里去了?

    转自:http://blogread.cn/it/article/6264?f=wb2 有时在Linux下会碰到这样的问题:ps aux看到的RSS内存只有不到30M,但是free看到内存却已经使用了 ...

  6. 6. SQL Server数据库监控 - 如何告警

    原文:6. SQL Server数据库监控 - 如何告警 常用的告警方式大致有:短信.邮件.应用程序 (beep提示,图标提示,升窗提示等),可是不能一直坐在电脑前看着应用程序,或者用脚本部署监控,根 ...

  7. C# 通过扩展WebBrowser捕获网络连接错误信息

    想捕获WebBrowser连接指定网站过程中发生的错误信息,包括网络无法连接.404找不到网页等等错误!经过网上的搜集,找到了以下解决方案,该解决方案不会在网站连接前发出多余的测试请求. 向Webbr ...

  8. JQuery Smart UI

    JQuery Smart UI 个人开发的一套使用htm+js的开发框架 SmartUI2.0后续声明 摘要: 感谢很多朋友关注,因为今年一直在另外一个公司做顾问,网络环境管制相当严格,所以一直没有更 ...

  9. Smarty从配置文件读取的变量

    从配置文件读取的变量 配置文件中的变量需要通过用两个"#"或者是smarty的保留变量 $smarty.config.来调用(下节将讲到) 第二种语法在变量作为属性值并被引号括住的 ...

  10. Attribute Routing

    Attribute Routing 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 题外话:由于这个技术点是新学的,并不属于原系列,但借助了原系列 ...