反射
来源:互联网 发布:红旗linux官网 编辑:程序博客网 时间:2024/06/05 20:44
一:什么是反射。
反射的概念:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
java中的反射:是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法
总结:简而言之Java的反射能在程序运行的时候,获取正在运行类中的属性和方法。并且还能访问、检测和修改他们的能力。
二:反射的基础Class类。
Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.
三:什么是字节码
字节码是一种中间码,它比机械码更抽象。它经常被看作是包含一个执行程序的二进制文件,更像一个对象模型。在java中,字节码是CPU构架(JVM)的具有可移植性的机械语言。
四:写java反射类一般的两步骤:
第一步:获取类的字节码;获取方法有四种:
第一种:运用getClass() 注:每个class 都有此函数
第二种:运用Class.getSuperclass() 通过子类求出父类的字节码
第三种:运用Class.forName()(最常被使用)。通过用Class类中的方法
第四种:运用primitive wrapper classes的TYPE 语法,这个有局限性只能用于 九个预定义的对象:八个基本数据对象 + void
举例:
String str1 = "abc";
第一种:Class cls1 = str1.getClass(); 或者Class cls2 = String.class;
第二种:Class c2 = cls1.getSuperclass();
第三种:Class cls3 = Class.forName("java.lang.String");
第四种:Class c1 = Boolean.TYPE;
第二步:使用java的api,常用的操作类有。
Field类:简单的理解可以把它看成一个封装反射类的属性的类。
//构造一个含构造方法的变量
- public class ReflectPoint {
- private int x;
- public int y;
- public ReflectPoint(int x, int y) {
- super();
- this.x = x;
- this.y = y;
- }
- }
得到某个类中的某个public成员变量:
例:Field filedY = pt1. getClass.getField(“y”);
打印某个类中的某个public成员变量:
System.out.println(fieldY.get(pt1));
得到某个类中的某个private成员变量:
Field filedX = pt1. getClass.getDeclaredfield(“x”);
打印某个类中的某个private成员变量:
fieldX.setAccessible(true);
System.out.println(fieldx.get(pt1));
Constructor类:Constructor类则封装了反射类的构造方法。
得到某个类所有的构造方法:
例:Constructor[] constructor = Class.forName(“java lang String”).getCoustructor();
得到某一个的构造方法:
例:Constructor constructor =
Class.forName(“java lang String”).getCoustructor(StringBuffer.class);
创建实例对象。
通常方式:
String str = new String(new StringBuffer(“abc”));
反射方式:
String str = (String)constructor.newInstance(new StringBuffer(“abc”));
Method类:它是用来封装反射类方法的一个类。
//方法与对象时没有关系的。参数(方法的名字,参数类型)
String Str1 = "abc";
获取某个对象的方法。
Method methodCharAt = String.class.getMethod("charAt", int.class);
调用某个对象方法中的方法。
//invoke意思是调用,方法对象中的方法。(对象名,传入的参数)
System.out.println(methodCharAt.invoke(Str1, 1));
//如果invoke(null, 1)第一个参数为null,则这个方法是静态方法。
五:数组与Object之间注意事项。
1.数组是基础类型(int,byte,short,long, char, double,float ,boolean )的数组就不能存入Object数组内;
例:int[] a1 = new int[]{1,2,3};
Object[] obj = a1;//是错误的。
原因:Object[]内部要装的是Object类型的元素,而int[] a1内装的是int类型的数组(基本类型),所以错误。
2.数组不是基本类型时,数组存入Object数组时要拆包。
例:
int[] a1 = new int[]{1,2,3};
String[] a4 = new String[]{"a","b","c"};
sop(Arrays.asList(a1));//打印的是[[I@3d4b7453]
sop(Arrays.asList(a4));//打印的是[a, b, c]
原因:jdk1.4中的asList接收的是Object的数组,因为是int类型,所以和Object[]数组对不上, 所以跳到jdk1.5版本中T... a可变参数的Object,但这Object当做是一个参数
五:数组的反射
1.创建数组打印的类,所以要获取字节码,数组长度。
- public static void printObject(Object obj){
- Class<? extends Object> 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));
- }
- }else{
- System.out.println(obj);
- }
- }
2.就是对数组就会拆包,对不是数组就打印。
- printObject(a4);
- printObject("xcv");
- printObject(a1);
打印结果:
a
b
c
xcv
1
2
3
六:反射实现框架功能:
框架(Framework):
是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用
方面而后者是从目的方面给出的定义。
框架与工具的区别:
工具被用户的类调用,而框架则是调用用户提供的类。
框架解决的核心问题:
1.框架要顾及以后写的类。
2.框架不能new实例对象,而是要用反射类获取。
框架举例:
- package fanshe2;
- //用反射做框架
- import java.io.FileInputStream;
- import java.io.InputStream;
- import java.util.Collection;
- import java.util.Properties;
- public class ReflectTest3 {
- public static void main(String[] args) throws Exception{
- // TODO Auto-generated method stub
- InputStream ips = ReflectTest3.class.getClassLoader().getResourceAsStream("config2.properties");
- Properties props = new Properties();
- props.load(ips);
- ips.close();//要马上关闭资源,因为这样系统资源会泄露。
- String className = props.getProperty("className");
- Collection collections = (Collection)Class.forName(className).newInstance();
- ReflectPoint pt1= new ReflectPoint(3,3);
- ReflectPoint pt2= new ReflectPoint(5,5);
- ReflectPoint pt3= new ReflectPoint(3,3);
- collections.add(pt1);
- collections.add(pt2);
- collections.add(pt3);
- collections.add(pt1);
- System.out.println(collections.size());
- }
- }
在反射中配置文件的设置方法://配置文件名叫config.properties
//配置文件方式一:-------------------------------------------------------------------------------------------
//config2.properties为相对路径,相对于当前工作目录
//InputStream ips = new FileInputStream("config2.properties");
//绝对路径例:("d:\\config2.properties");
//真正实际用途是配置出来的。就是用完整的路径,但完整的不是硬编码,而是运算出来的。getReal.path();
//配置文件方式二:用类加载器----------------------------------------------------------------------------
//InputStream ips = ReflectTest3.class.getClassLoader().getResourceAsStream("config2.properties");
//如果("config2.properties")这样写,则去classPath的根目录下逐个找"config2.properties"该文件。
//如果("fanshe2/config2.properties")
//类加载器方法的缺点只能读取文件,不能写文件。方式一还能写文件用OutputStream.
//配置文件方式三:用类方法:-------------------------------------------------------------------------------
InputStream ips = ReflectTest3.class.getResourceAsStream("config2.properties");
//如果配置文件不再自己的包内,则直接写成:
//InputStream ips = ReflectTest3.class.getResourceAsStream("fanshe22/config2.properties");
//如果所在的包名加入了/,则要完整的包名因为他是绝对路径了。
//InputStream ips = ReflectTest3.class.getResourceAsStream("完整的包路径/所在的包名/config2.properties");
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- Android 高仿微信实时聊天 基于百度云推送
- Linked List Cycle II
- C++中#if #ifdef 的作用
- 黑马程序员-关于C语言多文件联合输出
- cocoaPods的安装和使用
- 反射
- 百度Push(云推送)使用基础篇
- centOS7.0设置默认进入字符界面
- Why Singletons are Evil
- 【Linux入门学习之】vi/vim编辑器必知必会
- 每天记录一点点
- Binary Tree Inorder Traversal
- [ALSA学习]在ARM上遇到的问题
- 1623