Java-深入了解知识总结
2011-07-05 08:56
706 查看
===============eclipse开发工具================
Myeclipse是eclipse的插件。
Window-->Preference-->java-->compalier设置默认编译器版本
installed JREs//配置运行时版本
Window-->Preference-->General-->keys -->content Assist(内容助理)配置快捷键
Perpective与view,透视图与视图;若干视图的集合是透视图
运行的环境版本要与编译器版本相同或高于编译器版本。
Java模版代码:Window-->Preference-->java-->Editor-->Templates,使用方法:选中,右键Surround with。
导入已有工程:①将工程放在工作台目录下后,File->Import->在Import窗口中,选General下的“Existing projects into Workspace(已存在工程)”-->next-->找所需导入工 程,完成导入②JDK环境不同时,工程上右键-->Build Path-->config buildpath-->删除旧库-->增加新库(Add Library...)
==========Java5的一些简单新特性===============
静态导入
import语句可以导入一个类或某个包中的类
import static语句导入一个类中的某个静态方法或所有静态方法
Math.random() max(3,6)
可变参数 veriableParameter
特点:只能出现在参数列表的最后
...位于变量类型和变量名之间,前后有无空格都可以
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
public static int add(int x,int... args){
int sum = x;
int (i=0;i<args.length;i++)
{sum +=arg(i);}
return sum;
}
用System.out.printiln(add(1,2,3))调用
增强for循环
for(type 变量名:集合变量名){...}
注意事项:迭代变量必须在()中定义!
集合变量可以是数组或实现了iterable接口的集合类
编程举例:
public static int add(int x,int ... args){
int sum = x;
for(int arg:args){
sum+=arg;
}
return sum;
}
数据类型的自动装箱和拆箱
装箱:自动把一个,如基本数据类型装成一个对象。如,Integer iObj=2;JDK1.5之前,需要:Integer iObj = new Integer(2);
拆箱:把对象转换成基本数据类型。如:System.out.println(iObj+12);
下例中:
Integer i1 = 137;
Integer i2 = 137;
在一个字节之内,-128-127之间的数据,缓存起来所以相等
享元模式flyweight。
System.out.println(i1=i2)
结果:false
========================= java5的枚举 ==================
枚举
枚举就是让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
将值提前规定好。
编程实例:用普通类实现枚举功能,定义一个Weekday的类来模拟枚举功能。
①私有的构造方法
②每个元素分别用一个公有的静态成员变量表示
③可以有若干公有方法和抽象方法,例如,要提供nextday方法必须是抽象的,
④!!!采用抽象方法定义nextday就将大量的if.else语句转移成一个个独立的类。
枚举的基本应用
举例:定义一个Weekday的枚举
public enum WeekDay{
SUN.MON,TUE,WED,THT,FRI.SAT;
}
总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,例如可以调用
枚举 就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。
枚举元素必须位于枚举体中的最开始部分,枚举元素列表的最后要有分号与其它成员分隔。成员方法或变量放在枚举元素的前面,编译器报告错误。
带构造方法的枚举:
①构造方法必须定义成私有的
如: public enum WeekDay{
SUN(1),MON(),TUE,WED,THI,FRI,SAT;
private WeekDay(){System.out.println("first");}
private WeekDay(int day)
{System.out.println("second");}
}
②如果有多个构造方法,该如何选择哪个构造方法?
在枚举元素的后面跟上(),就表示创建元素指向的实例对象的时候,使用哪个构造方法。
③枚举元素MON和MON()的效果一样,都是调用默认的构造方法
带抽象方法的枚举
①定义枚举TraffcLamp
②实现普通的next方法
③实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义
增加上表示时间的构造方法
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time =time;}
}
枚举只有一个成员时,就可以作为一种单例的实现方式。
========================= 反射的深入讲解 ===============
反射的基石 Class类
Class类
Java程序中的各个Java类属于同一类事物
Class cls1 = Date.class//字节码1;
Class cls1 = Person.class//Person类的字节码;
p1.getClass();
Class.forName("java.lang.String")//"java.lang.String"指定这个类完整名称
得到字节码方式有三种:
①类名.class
②对象.getClass(),例如,new date().getclass()
③Class.forName("类名"),例如,class.forName("java.util.date")
九个预定义Class实例对象(八类基本数据类型+Void)
Class.isPrimtive方法//是否是基本类型:
int.class == integer.TYPE//基本类型表示方法integer.TYPE
数组类型的实例对象
class.isArray()
总之,只要在源程序中出现的类型,都有各自的 Class实例对象
反射:
反射就是把java类中的各种成分映射成相应的Java类。
例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造函数,包等信息也用一个个的Java类来表示。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Filed、Method(方法)、Contructor(构造方法)、Package等等。
①Constructor类:得到某个类所有的构造方法:
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
②Field类:代表某个类中的一个成员变量
Field fieldY = pt1.getClass().getField("y")
将所有String定义的字符中的"b"改为"a"!
private static void changeStringValue(Object obj) throws Exception
Field[] fields =obj.getClass().getFields();
for(Field field : field){
//if (field.getType().equals(String.class)){
if (field.getType().equals(String.class)){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b','a');
field.set(obj,newValue);
}
③Method类(类里面的方法,不是对象中的):得到类中的某一个方法
如 :Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:System.out.println(charAt.invoke(str,1));
通常方式:System.out.println(str.charAt(1));
如果传递给Method对象的invoke()方法的第一个参数是null,说明 该Method对象对应的是一个静态方法。
用反射方法执行某个类中的main方法
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//每个数组的父类都是Object
mainMethod.invoke(null,(Object)new String[]{"xxx"});编译器会做特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
ArrayList_HashSet的比较及Hashcode分析
ArrayList,是有顺序的集合,相当于数组,每一个值无论重复都能放进去;HashSet:先判断有无相同对象,有相同的则不放,若要覆盖原内存必须先remove再add 。
HashSet就是采用哈希算法存储对象的集合,它内部采用对某个数字进行取余的方式对哈希码进行分组和划分对象的存储区域。object类中定义了一个hashCode()方 法来返回每个对象的哈希码,当从HashSet集合中查找某个对象时,java系统首先调用对象的hashCode()方法获取该对象的哈希码,然后根据哈希码找到相应存储区域,最后取出该区域的每个元素与该对象进行equals方法比较,这样就不用遍历整个集合就可以得到结论。
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,这样就无法找到该对象,这也导致无法从HashSet中单独删除当前对象,从而造成内存泄漏。
用类加载器的方式管理资源和配置文件
getRealPath();//先获取安装位置,然后再在程序内部用算法加上内部配置文件文件的位置
. class类加载器 getClassloader()
getResourceAsStream()
了解Javabean
内省 introSpector-->Javabean-->特殊的Java类
Javabean的名称根据方法来,除去set、get剩下来的名称就是Javabean的i名称
Age-->如果第二个字母是小的,则把第一个字母变成小的-->age
getCPU--》CPU
一个符合Javabean特点的类可以当作普通类一样进行使用,但把它当JavaBean方式进行操作
PropertyDescriptor 属性描述符
使用BeanUtils工具包操作JavaBean
添加BeanUtils jar包操作:在工程目录下创建lib文件夹并把jar包复制到这里来,选择jar包右键选择Build Path->Add to Build Path
同时还要用到日记开发包logging,也增加到Build Path
BeanUtils工具包举例:
BeanUtils.getProperty(pt1, "x");
BeanUtils.setProperty(pt1, "x", "9");
BeanUtils.setProperty(pt1, "birthday.time", "111");
System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));
PropertyUtils.setProperty(pt1, "x", 9);
========================java5的注解===================
@suppressWarnings 压缩警告,忽略提示 @Deprecated 声明方法过时(标志) @Override 覆盖
元注解,即注解的注解,@RetetionPolicy有三种取值:RetetionPolicy.SOURCE、Retetion.CLASS、RetetionPolicy.RUNTIME分别对应的生命周期:java源文件-->class文件-->内存中的字节码
为注解增加基本属性
public @interface ItcastAnnotation {
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,4};//数组类型属性
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举属性
MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");//注释类型属性
}
======================== java5的泛型 ===================
泛型是提供给javac编译器使用的,可以限定集合中的输入类型。泛型通过<>来指定要限制数据类型。
泛型是提供给javac用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除类型信息,使程序运行效率不受影响,编译参数化的泛型集合,其字节码值相等,其字节码去掉泛型的类型信息,只要能跳过编译器,就能往某泛型集合中加入其他类型信息。
泛型集合的综合应用案例
HashMap<String,Integer> maps = new HashMap<String, Integer>();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry : entrySet){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
自定义泛型类的应用
如:在类身上定义泛型
public class GenericDao<E> {
public void add(E x){
}
public E findById(int id){
return null;
}
}
通过反射获得泛型的实际类型参数
得到方法的参数的实际类型
public static void applyVector(Vector<Date> v1){
}
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
=================类加载器的深入讲解与应用=============
类加载器
默认三个主要类加载器:
BootStrap、ExClassLoader、AppClassLoader
类加载器的委托机制
编写自己的类加载器:
自定义的类加载器继承ClassLoader,必须覆盖findClass(),不用loadClass()为了保留里面的流程;defineClass():将字节数组转换成class。
①编写加密的工具类
public static void (string args[]) throws Exception{
String srcpath =args[0];//源
String destDir = args[1];//
FileInputStream fis =new FileInputStream(srcPath);
String destFileName = srcPath.substring(srcPath.lastIndex('/')+1);
String destFilePath = destDir + " \\"+destfileName;
FileInputStream fis =new FileInputStream(destPath);
cypher(fis,fos);
fis.close();
ops.close();
}
private static void cypher(InputStream ips,OutputStream ops) throws Exception{
int b = -1;
while((b=ips.read()) != 1){
ops.write(b^0xff);//异或运算
}
}
②编写解密的工具类
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName = classDir + "//" + name.substring(name.lastIndexOf('.')+1) + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
System.out.println("aaa");
byte[] bytes = bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
==================动态代理技术的深入讲解==============
代理的概念与作用
采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置使用目标类、还是代理类,这样以后很容易切换。
AOP: Aspect oriented program,面向方面的编程,交叉业务的编程问题。
安全事务日志功能要贯穿到多个模块中,所以他们就是交叉业务。
动态代理技术:
JVM可以在运行期动态生成出类的字节码,这种动态生成类往往被用作代理类,即动态代理类。JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作相同接口的目标类的代理。如果为没有实现接口的类生成动态代理类,那么可以使用CGLIB库,CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理。
添加系统功能代码:
1在调用目标方法之前
2在调用目标方法之后
3在调用目标方法前后都有
4在处理目标方法异常的catch块中
创建动态类
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);//得到Class
System.out.println("clazzProxy1.getName()");
Constructor[] constructor = clazzProxy1.getConstruction
for(Constructor constructor:constructors){
string name = consturctor.getname();
}
$Proxy0(InvocationHandler,int )
代理类编程示例:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
/**
* @param args
*/
@SuppressWarnings({"unchecked","unused"})
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy.getName());
System.out.println("------------begin constructors list--------------");
/*$Proxy0()
$Proxy0(InvocationHandler,int)*/
Constructor[] constructors = clazzProxy.getConstructors();
for(Constructor constructor:constructors){
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();
for(Class clazzParam:clazzParams ){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams !=null&&clazzParams.length!=0)
{
sBuilder.deleteCharAt(sBuilder.length() -1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("------------begin methods list--------------");
Method[] methods = clazzProxy.getMethods();
for(Method method:methods){
String name = method.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();
for(Class clazzParam:clazzParams ){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams !=null&&clazzParams.length!=0)
{
sBuilder.deleteCharAt(sBuilder.length() -1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("------------begin create instance object--------------");
//Object obj = clazzProxy.newInstance();//此处不可以调用该方法,因为这个类没有默认的构造方法
//1.采用内部类的方式得到Collection的代理实例
Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);
class MyInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}
Collection proxy = (Collection) constructor.newInstance(new MyInvocationHandler());
System.out.println(proxy);//此处打印的结果是null是因为proxy.toString()返回的结果是null
System.out.println(proxy.toString());//此处打印的结果是null
proxy.clear();//调用没有返回值的方法时没有问题。
//proxy.size();//调用有返回值的方法的时候报告错误:Exception in thread "main" java.lang.NullPointerException
//2.采用匿名的内部类的方式(即直接new 接口InvocationHandler(){}的形式)得到Collection的代理实例
Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
});
//3.用Proxy.newInstance方法直接一步就创建出代理对象Collection的代理实例。
Collection proxy2 = (Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
ArrayList target = new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");
return retVal;
}
});
proxy2.add("zxx");
proxy2.add("lhm");
proxy2.add("bxd");
System.out.println(proxy2.size());
}
}
Myeclipse是eclipse的插件。
Window-->Preference-->java-->compalier设置默认编译器版本
installed JREs//配置运行时版本
Window-->Preference-->General-->keys -->content Assist(内容助理)配置快捷键
Perpective与view,透视图与视图;若干视图的集合是透视图
运行的环境版本要与编译器版本相同或高于编译器版本。
Java模版代码:Window-->Preference-->java-->Editor-->Templates,使用方法:选中,右键Surround with。
导入已有工程:①将工程放在工作台目录下后,File->Import->在Import窗口中,选General下的“Existing projects into Workspace(已存在工程)”-->next-->找所需导入工 程,完成导入②JDK环境不同时,工程上右键-->Build Path-->config buildpath-->删除旧库-->增加新库(Add Library...)
==========Java5的一些简单新特性===============
静态导入
import语句可以导入一个类或某个包中的类
import static语句导入一个类中的某个静态方法或所有静态方法
Math.random() max(3,6)
可变参数 veriableParameter
特点:只能出现在参数列表的最后
...位于变量类型和变量名之间,前后有无空格都可以
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
public static int add(int x,int... args){
int sum = x;
int (i=0;i<args.length;i++)
{sum +=arg(i);}
return sum;
}
用System.out.printiln(add(1,2,3))调用
增强for循环
for(type 变量名:集合变量名){...}
注意事项:迭代变量必须在()中定义!
集合变量可以是数组或实现了iterable接口的集合类
编程举例:
public static int add(int x,int ... args){
int sum = x;
for(int arg:args){
sum+=arg;
}
return sum;
}
数据类型的自动装箱和拆箱
装箱:自动把一个,如基本数据类型装成一个对象。如,Integer iObj=2;JDK1.5之前,需要:Integer iObj = new Integer(2);
拆箱:把对象转换成基本数据类型。如:System.out.println(iObj+12);
下例中:
Integer i1 = 137;
Integer i2 = 137;
在一个字节之内,-128-127之间的数据,缓存起来所以相等
享元模式flyweight。
System.out.println(i1=i2)
结果:false
========================= java5的枚举 ==================
枚举
枚举就是让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
将值提前规定好。
编程实例:用普通类实现枚举功能,定义一个Weekday的类来模拟枚举功能。
①私有的构造方法
②每个元素分别用一个公有的静态成员变量表示
③可以有若干公有方法和抽象方法,例如,要提供nextday方法必须是抽象的,
④!!!采用抽象方法定义nextday就将大量的if.else语句转移成一个个独立的类。
枚举的基本应用
举例:定义一个Weekday的枚举
public enum WeekDay{
SUN.MON,TUE,WED,THT,FRI.SAT;
}
总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,例如可以调用
枚举 就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。
枚举元素必须位于枚举体中的最开始部分,枚举元素列表的最后要有分号与其它成员分隔。成员方法或变量放在枚举元素的前面,编译器报告错误。
带构造方法的枚举:
①构造方法必须定义成私有的
如: public enum WeekDay{
SUN(1),MON(),TUE,WED,THI,FRI,SAT;
private WeekDay(){System.out.println("first");}
private WeekDay(int day)
{System.out.println("second");}
}
②如果有多个构造方法,该如何选择哪个构造方法?
在枚举元素的后面跟上(),就表示创建元素指向的实例对象的时候,使用哪个构造方法。
③枚举元素MON和MON()的效果一样,都是调用默认的构造方法
带抽象方法的枚举
①定义枚举TraffcLamp
②实现普通的next方法
③实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义
增加上表示时间的构造方法
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time =time;}
}
枚举只有一个成员时,就可以作为一种单例的实现方式。
========================= 反射的深入讲解 ===============
反射的基石 Class类
Class类
Java程序中的各个Java类属于同一类事物
Class cls1 = Date.class//字节码1;
Class cls1 = Person.class//Person类的字节码;
p1.getClass();
Class.forName("java.lang.String")//"java.lang.String"指定这个类完整名称
得到字节码方式有三种:
①类名.class
②对象.getClass(),例如,new date().getclass()
③Class.forName("类名"),例如,class.forName("java.util.date")
九个预定义Class实例对象(八类基本数据类型+Void)
Class.isPrimtive方法//是否是基本类型:
int.class == integer.TYPE//基本类型表示方法integer.TYPE
数组类型的实例对象
class.isArray()
总之,只要在源程序中出现的类型,都有各自的 Class实例对象
反射:
反射就是把java类中的各种成分映射成相应的Java类。
例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造函数,包等信息也用一个个的Java类来表示。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Filed、Method(方法)、Contructor(构造方法)、Package等等。
①Constructor类:得到某个类所有的构造方法:
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
②Field类:代表某个类中的一个成员变量
Field fieldY = pt1.getClass().getField("y")
将所有String定义的字符中的"b"改为"a"!
private static void changeStringValue(Object obj) throws Exception
Field[] fields =obj.getClass().getFields();
for(Field field : field){
//if (field.getType().equals(String.class)){
if (field.getType().equals(String.class)){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b','a');
field.set(obj,newValue);
}
③Method类(类里面的方法,不是对象中的):得到类中的某一个方法
如 :Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:System.out.println(charAt.invoke(str,1));
通常方式:System.out.println(str.charAt(1));
如果传递给Method对象的invoke()方法的第一个参数是null,说明 该Method对象对应的是一个静态方法。
用反射方法执行某个类中的main方法
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//每个数组的父类都是Object
mainMethod.invoke(null,(Object)new String[]{"xxx"});编译器会做特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
ArrayList_HashSet的比较及Hashcode分析
ArrayList,是有顺序的集合,相当于数组,每一个值无论重复都能放进去;HashSet:先判断有无相同对象,有相同的则不放,若要覆盖原内存必须先remove再add 。
HashSet就是采用哈希算法存储对象的集合,它内部采用对某个数字进行取余的方式对哈希码进行分组和划分对象的存储区域。object类中定义了一个hashCode()方 法来返回每个对象的哈希码,当从HashSet集合中查找某个对象时,java系统首先调用对象的hashCode()方法获取该对象的哈希码,然后根据哈希码找到相应存储区域,最后取出该区域的每个元素与该对象进行equals方法比较,这样就不用遍历整个集合就可以得到结论。
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,这样就无法找到该对象,这也导致无法从HashSet中单独删除当前对象,从而造成内存泄漏。
用类加载器的方式管理资源和配置文件
getRealPath();//先获取安装位置,然后再在程序内部用算法加上内部配置文件文件的位置
. class类加载器 getClassloader()
getResourceAsStream()
了解Javabean
内省 introSpector-->Javabean-->特殊的Java类
Javabean的名称根据方法来,除去set、get剩下来的名称就是Javabean的i名称
Age-->如果第二个字母是小的,则把第一个字母变成小的-->age
getCPU--》CPU
一个符合Javabean特点的类可以当作普通类一样进行使用,但把它当JavaBean方式进行操作
PropertyDescriptor 属性描述符
使用BeanUtils工具包操作JavaBean
添加BeanUtils jar包操作:在工程目录下创建lib文件夹并把jar包复制到这里来,选择jar包右键选择Build Path->Add to Build Path
同时还要用到日记开发包logging,也增加到Build Path
BeanUtils工具包举例:
BeanUtils.getProperty(pt1, "x");
BeanUtils.setProperty(pt1, "x", "9");
BeanUtils.setProperty(pt1, "birthday.time", "111");
System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));
PropertyUtils.setProperty(pt1, "x", 9);
========================java5的注解===================
@suppressWarnings 压缩警告,忽略提示 @Deprecated 声明方法过时(标志) @Override 覆盖
元注解,即注解的注解,@RetetionPolicy有三种取值:RetetionPolicy.SOURCE、Retetion.CLASS、RetetionPolicy.RUNTIME分别对应的生命周期:java源文件-->class文件-->内存中的字节码
为注解增加基本属性
public @interface ItcastAnnotation {
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,4};//数组类型属性
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举属性
MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");//注释类型属性
}
======================== java5的泛型 ===================
泛型是提供给javac编译器使用的,可以限定集合中的输入类型。泛型通过<>来指定要限制数据类型。
泛型是提供给javac用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除类型信息,使程序运行效率不受影响,编译参数化的泛型集合,其字节码值相等,其字节码去掉泛型的类型信息,只要能跳过编译器,就能往某泛型集合中加入其他类型信息。
泛型集合的综合应用案例
HashMap<String,Integer> maps = new HashMap<String, Integer>();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry : entrySet){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
自定义泛型类的应用
如:在类身上定义泛型
public class GenericDao<E> {
public void add(E x){
}
public E findById(int id){
return null;
}
}
通过反射获得泛型的实际类型参数
得到方法的参数的实际类型
public static void applyVector(Vector<Date> v1){
}
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
=================类加载器的深入讲解与应用=============
类加载器
默认三个主要类加载器:
BootStrap、ExClassLoader、AppClassLoader
类加载器的委托机制
编写自己的类加载器:
自定义的类加载器继承ClassLoader,必须覆盖findClass(),不用loadClass()为了保留里面的流程;defineClass():将字节数组转换成class。
①编写加密的工具类
public static void (string args[]) throws Exception{
String srcpath =args[0];//源
String destDir = args[1];//
FileInputStream fis =new FileInputStream(srcPath);
String destFileName = srcPath.substring(srcPath.lastIndex('/')+1);
String destFilePath = destDir + " \\"+destfileName;
FileInputStream fis =new FileInputStream(destPath);
cypher(fis,fos);
fis.close();
ops.close();
}
private static void cypher(InputStream ips,OutputStream ops) throws Exception{
int b = -1;
while((b=ips.read()) != 1){
ops.write(b^0xff);//异或运算
}
}
②编写解密的工具类
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName = classDir + "//" + name.substring(name.lastIndexOf('.')+1) + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
System.out.println("aaa");
byte[] bytes = bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
==================动态代理技术的深入讲解==============
代理的概念与作用
采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置使用目标类、还是代理类,这样以后很容易切换。
AOP: Aspect oriented program,面向方面的编程,交叉业务的编程问题。
安全事务日志功能要贯穿到多个模块中,所以他们就是交叉业务。
动态代理技术:
JVM可以在运行期动态生成出类的字节码,这种动态生成类往往被用作代理类,即动态代理类。JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作相同接口的目标类的代理。如果为没有实现接口的类生成动态代理类,那么可以使用CGLIB库,CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理。
添加系统功能代码:
1在调用目标方法之前
2在调用目标方法之后
3在调用目标方法前后都有
4在处理目标方法异常的catch块中
创建动态类
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);//得到Class
System.out.println("clazzProxy1.getName()");
Constructor[] constructor = clazzProxy1.getConstruction
for(Constructor constructor:constructors){
string name = consturctor.getname();
}
$Proxy0(InvocationHandler,int )
代理类编程示例:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
/**
* @param args
*/
@SuppressWarnings({"unchecked","unused"})
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy.getName());
System.out.println("------------begin constructors list--------------");
/*$Proxy0()
$Proxy0(InvocationHandler,int)*/
Constructor[] constructors = clazzProxy.getConstructors();
for(Constructor constructor:constructors){
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();
for(Class clazzParam:clazzParams ){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams !=null&&clazzParams.length!=0)
{
sBuilder.deleteCharAt(sBuilder.length() -1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("------------begin methods list--------------");
Method[] methods = clazzProxy.getMethods();
for(Method method:methods){
String name = method.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();
for(Class clazzParam:clazzParams ){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams !=null&&clazzParams.length!=0)
{
sBuilder.deleteCharAt(sBuilder.length() -1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("------------begin create instance object--------------");
//Object obj = clazzProxy.newInstance();//此处不可以调用该方法,因为这个类没有默认的构造方法
//1.采用内部类的方式得到Collection的代理实例
Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);
class MyInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}
Collection proxy = (Collection) constructor.newInstance(new MyInvocationHandler());
System.out.println(proxy);//此处打印的结果是null是因为proxy.toString()返回的结果是null
System.out.println(proxy.toString());//此处打印的结果是null
proxy.clear();//调用没有返回值的方法时没有问题。
//proxy.size();//调用有返回值的方法的时候报告错误:Exception in thread "main" java.lang.NullPointerException
//2.采用匿名的内部类的方式(即直接new 接口InvocationHandler(){}的形式)得到Collection的代理实例
Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
});
//3.用Proxy.newInstance方法直接一步就创建出代理对象Collection的代理实例。
Collection proxy2 = (Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
ArrayList target = new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");
return retVal;
}
});
proxy2.add("zxx");
proxy2.add("lhm");
proxy2.add("bxd");
System.out.println(proxy2.size());
}
}
相关文章推荐
- 了解OutOfMemoryError异常 - 深入Java虚拟机读后总结
- 暂时不太了解, 需要深入了解的一些java知识(仅做备注使用了。)
- 总结与JAVA需要了解的知识
- Java基础知识学习总结(一)---深入理解Java的接口和抽象类
- java零碎知识总结(不断更新中)
- 超详细的Java面试题总结(一)之Java基本知识
- 【Java基础总结】-了解Java线程调度、并发安全及锁优化
- JavaIO知识总结----温故才能知新02
- java基础知识总结3
- 【JAVA基础知识总结】Java I/0流概述以及使用方法
- java后台面试相关知识总结(3)
- struts2基础知识了解(总结)
- JAXP(Java API for XMLProcessing)知识总结
- 黑马程序员_java基础知识总结(1)面向对象基础总结
- Java知识总结-多线程
- Java 基础知识总结
- java开发知识总结1
- java初学者知识小总结-01(byte数据类型赋值出错)
- Java知识总结(一)
- 深入了解JAVA可变长度的参数(Varargs)