黑马程序员_Java高新技术——反射,常见名词解释

来源:互联网 发布:微信领淘宝卷是真的吗 编辑:程序博客网 时间:2024/06/07 17:48

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

名词解释:
---------------------------------------------------------------------------------------------------------------------------------------- 
1、IDE:ItegrityDevelopment Enviroment,集成开发环境
2、JavaEE:javaEnterprise Edition:java企业版开发工具。
3、JMS:Java MessageService,Java消息服务,是一个Java平台中关于面向消息中间件的API,用于在两个应用程序间,或分布式系统中,发送消息,进行异步通信。
4、JMX:Java ManagementExtensions,Java管理扩展;是一个为应用程序、设备、系统植入管理功能的框架。
5、JNDI:Java Nameingand Directory Interface:Java命名和目录接口。
6、JDBC:Java DataBase Connectivity:Java数据库连接。
7、MVC:MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用于组织代码用一种业务逻辑和数据显示分离的方法
8、JSF:java Server Faces,他与struts一样都是web应用框架,但他们是两种不同性质的框架!struts只是单纯的MVC模式框架(MVC就不用多解释了吧,j2ee常见的设计模式),
而JSF是一种事件驱动型的组件模型! 通过JSF,可以在网页上使用WEB组件来捕获用户行为产生的事件.
使用JSF开发web程序将与开发swing程序类似,可以拖放控件!(JSF和struts的区别)


透视图
overload vs override
享元模式 flyweight

有很多个小的对象,他们有很多相同的地方,把他们变成一个对象!
不同的属性,把他们变成方法的参数,称之为外部状态!
相同的属性称之为内部状态!

-----------------------------------------------------------------------------------------------------------------------------
反射的概念:
反射就是把Java类中的各种成分映射成相应的java类。
例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,
就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,
这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等
 -----------------------------------------------------------------------------------------------------------------------------

反射的基石:Class类。
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类的类名就是Class。
 
获取Class对象的三种方式:
 
1.Object中的getClass方法。对象.getClass
例如:new Date().getClass();
 

2.任何数据类型都具备的静态属性。类名.class
例如:System.class
 
3.通过给定的类的字符串名称使用Class.forName()方法类获取该类。
例如:Class.forName("java.util.Date");
 
相关面试题: Class.forName()的作用。
 
作用是返回字节码文件,返回的方式有两种。
 
1.这份字节码曾经被加载过,已经在java虚拟机中,直接返回。
2.虚拟机中没有这份字节码,用类加载器加载。加载进的字节码缓存在虚拟机中。
 
九个预定义类型的实例对象:
 
基本的 Java 类型(boolean、byte、char、short、int、long、float 和double)和关键字void 也表示为Class对象。
基本类型的字节码获取方式只有一种就是类名.class。例如int.class;void.class 
数组也是一种Class的实例对象。
数组类型的Class实例对象:

/** * 反射类 * @author 张熙韬 */public static void main(String[] args) throws Exception {String str1 = "abc";Class cls1 = str1.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String");System.out.println(cls1 == cls2);System.out.println(cls1 == cls3);System.out.println(cls2 == cls3);// 是否是原始类型???不是的System.out.println(cls1.isPrimitive());         //falseSystem.out.println(int.class.isPrimitive());    //trueSystem.out.println(int[].class.isPrimitive());  //falseSystem.out.println(int[].class.isArray());      //trueSystem.out.println(Integer.class.isPrimitive()); //falseSystem.out.println(int.class == Integer.class); //false// TYPE代表所包装类型的字节码System.out.println(int.class == Integer.TYPE);  //true} 
----------------------------------------------------------------------------------------------------------------------------------------------------
Constructor类代表某个类中的一个构造方法

得到某个类所有的构造方法:
例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一个构造方法:
例子:    Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
//获得方法时要用到类型

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

Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

该方法内部的具体代码是怎样写的呢?
答:用到了缓存机制来保存默认构造方法的实例对象。

反射会导致性能下降。

---------------------------------------------------------------------------------------------------------------------------------------------------
 获取Class中的字段Field类:
 
例:
ReflectPoint pt1 = new ReflectPoint(3, 5);
// 通过getField()方法,获取公共的字段
// fieldY的值是多少?不是5,它不是对象身上的变量,而是类上,要用它获取某个对象身上的值
Field fieldX = pt1.getClass().getField("x");
System.out.println(fieldX.get(pt1));
// 通过getDeclaredField(()方法获取私有方法
Field fieldY = pt1.getClass().getDeclaredField("y");
fieldY.setAccessible(true);// 对私有字段取消访问权限,暴力访问。
System.out.println(fieldY.get(pt1)); 
 
---------------------------------------------------------------------------------------------------------------------------------------------------
 
获取Class中的方法。Method类代表某个类中的一个成员方法。
 
Method[] methods = Class.forName("java.lang.String").gerMethods();//获取公有方法。
methods = Class.forName("java.lang.String").gerDeclearedMethods();//获取私有的方法
String str = "abc";  
Method methodcharAt = String.class.getMethod("charAt", int.class);  
methodcharAt.invoke(str,1);//b  
methodcharAt.invoke(str,new Object[]{2});//c  

例:调用主函数 

Method mainMethod = Class.forName(className).getMethod("main" String[].class);
mainMethod.invoke(null,newObject[]{new String[]{"abc","def"}});//jdk1.5为了兼容1.4会将传入的数组拆包,newObject是为了拆包后得到一个String类型的数组 
mainMethod.invoke(null,(Object)new String[]{"abc","def"});//强制类型转换为Object编译器会将String类型的数组当做对象来对待。
methodcharAt.invoke(null,1);//如果调用一个方法第一个参数是null,说明这个方法是静态的。
 
---------------------------------------------------------------------------------------------------------------------------------------------------
数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;
非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
------------------------------------------------------------------------------------------------------------------------------------------------
hashCode和内存泄露的问题!
答:为了保证一个类的实例对象能在HashSet正常存储,要求这个类的两个实例对象用equals
方法比较的结果相等时,他们的哈希码也必须相等。也就是说,如果
obj1.equals(obj2)的结果为true,那么以下表达式的结果也必须为true
obj1.hashCode()==obj2.hashCode()

如果没有满足上述要求,那么由于它们的hashCode()方法的返回值不同,第二个对象
首先按照哈希码计算可能会被放进与第一个对象不同的区域中。
因为Object类中的hashCode()方法它的返回值是通过对象的内存地址推算的。
所以当一个对象存储进HashSet集合中后,就不能修改这个对象中的那些参加计算
哈希值的字段了,否则,对象修改后的哈希值与最初的值不同了,
导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露!

如下:内存泄露!
InputStream ips=new FileInputStream("config.properties");Properties props=new Properties();props.load(ips);ips.close();Collection collections2=new HashSet();ReflectPoint pt1=new ReflectPoint(3, 3);ReflectPoint pt2=new ReflectPoint(5, 5);ReflectPoint pt3=new ReflectPoint(3, 3);collections2.add(pt1);collections2.add(pt2);collections2.add(pt3);collections2.add(pt1);/** * 内存泄露 */pt1.y=8;//hashCode的值已经被修改,哈希地址改变,所以无法删除元素collections2.remove(pt1);System.out.println(collections.size());System.out.println(collections2.size());}


---------------------------------------------------------------------------------------------------------------------------------------------------
 
使用反射技术开发框架的原理:
 
反射的作用-->实现框架功能:因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个实例对象,要用反射方式来获取。
框架与工具类的区别,工具类被用户的类调用,而框架则是调用用户提供的类。

给力的张老师的一个案例是这样的: 
我做房子卖给用户住,由用户自己安装门窗和空调,
我做的房子就是框架,用户需要使用我的框架,
把门窗插入进我提供的框架中。
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

用类加载器的方式管理资源和配置文件: 
注意:开发时要使用绝对路径,但是绝对路径不是硬编码,应该是运算出来的。
1.使用io读取流读取。
InputStream ips = new FileInputStream("路径");
 
2.使用类加载器加载。
InputStream ips = ReflectPoint.class.getClassLoaderAsStream("路径");//路径不能以/打头
 
类提供的简便方法加载:
 InputStream ips = ReflectPoint.class.getResourceAsStream("name");//用相对路径的话是相对于ReflectPoint包所在目录即可,也可以用绝对路径这时需要/打头。
---------------------------------------------------------------------------------------------------------------------------------------------------
两个反射的应用:/** * 使用反射技术打印元素 * @author 张熙韬 * @param obj */public static void printObject(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));}}else {System.err.println(obj);}}/** * 使用反射技术改变元素的值 * @author 张熙韬 * @param obj */public static void changeStringValue(Object obj) throws Exception{Field[] fields=obj.getClass().getFields();for(Field field:fields){if(field.getType()==String.class){String oldValue=(String) field.get(obj);String newValue=oldValue.replace('b', 'a');field.set(obj, newValue);}}} 

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------