----------- 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()); //false
System.out.println(int.class.isPrimitive()); //true
System.out.println(int[].class.isPrimitive()); //false
System.out.println(int[].class.isArray()); //true
System.out.println(Integer.class.isPrimitive()); //false
System.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学习型技术博客、期待与您交流! ------------