java基础
jdk1.5 新特征
1。静态导入
它实现将类中的静态方法导入文件中,例如import static java.lang.Math.*;
2。可变参数(一个方法接受的参数个数不固定)
只能出现在参数列表的最后;
...位于变量类型的变量名之间,前后有无空格都可以;
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
int... is它类似 int[] is,使用时可以数组的形式访问
3。增强for循环
for(type 变量名:集合变量){...}
迭代变量必须在()中定义
集合变量可以是数组或者实现了Iterable接口的集合类
4。基本数据类型的自动拆箱与装箱
自动装箱:Integer num =1; (多个装箱只能转换一个字节-128~127转换成同一个int类型对象,即享元模式:多个对象共享)
自动拆箱:System.out.println(num + 10);
5。枚举(enum)
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错,枚举
可以让编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目录。
a.枚举就相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。
b.枚举元素必须位于枚举体中的最开始部分,枚举元素列表后要有分号与其它成员变量分隔。
c.带构造方法的枚举:构造方法必须定义成私有的,如果多个构造方法,默认是空构造方法();
d.带方法的枚举:每个元素分别由枚举的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义
f.枚举只有一个成员时,就可以作为一种单例的实现方式
实例:
反射 (jdk 1.2后具有的特性)
反射的基石-》classs 类
1.java程序中的各个java类属于同一个类事物,描述这类名就是Class.
2.获取字节码的方式:
类名class,例如:System.class
对象.getClass(),例如:new Date().getClass();
Class.forName("类名"),例如:ClassName.forname("java.util.Date");
反射就是把java类中的各种成分映射成相应的java类。
Constructor类
getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法,newInstance() 创建此 Class 对象所表示的类的一个新实例
Field类
Field类代表某个类中的一个成员变量
Method类
Method类代表某个类中的一个成员方法
invoke(null,Class<?>);如果参数是null表示一个静态方法
Arrays.asList(Object);将数组对象转换成Array
演示例如:
2.集合类
HashSet储存时要hashCode、equals比较,保证储存的值不相同
当一个对象被存储进Hashset集合中以后,就不能修改这个对象中的那些参与
计算哈希值的字段了,否则对象修改后的哈希值与最初存储存HashSet集合中时哈希值
就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去
HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet
集合中单独删除当前的对象,从而造成内在泄露。
反射的作用-》实现框架功能
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
演示例如:
由内省引出JavaBean
JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合命名规则。
注解 (jd1.5新特征)
注解相当一种标记,java编译器,开发工具和其它程序可以用来反射标记,标记可以在包,类,字段,方法参数以及局部变量上。
Deprecated //过期
Override //重写覆盖
SuppressWarnings //取消显示指定的编译器警告(@SuppressWarnings("deprecation"))
@Retention(RetentionPolicy.RUNTIME) //保存在运行时(CLASS 保留策略默认,SOURCE 编译器要丢弃的注释)
@Target(ElementType.METHOD) //限制在方法声明使用 {ElementType.METHOD,ElementType.TYPE} TYPE(包括Class Interface Enum等)
泛型(jd1.5新特征)
泛型是提供java编译器使用的,可以限定集合中的输入类型,使程序运行效果不受影响。
AarryList<E>类定义和ArraryList<Integer>类引用中涉及如下术语:
整个称为ArrayList<E>泛型类型
整个ArraryList<Integer>称为参数化的类型
ArraryList<Interge>中的Interge称为类型参数的实例或实际类型参数
ArraryList<Interge>中的<> typeof
ArraryList称为原始类型
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报警告
原始类型可以引用一个参数化类型的对象,编译报警告
参数化类型不考虑参数的继承关系
在创建数组实例时,数组的元素不能使用参数化的类型,如下
Vector<Integer> verctor[] = new Vector<Integer>[10];//错误写法
使用?通配符可以用其它各种参数化的类型,?通配符定义的变量主要作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
限定通配符的上下边界:
限定通配符的上边界:如 Vector<? extends Number> x = new Vector<Integer>();
限定通配符的下边界:如 Vector<? super Interger> x = new Vector<Number>();
提示:限定通配符总是包括自己
泛型中的T代表任意类型。
只有引用类型才有泛型方法的实际参数,基本类型是没有泛型的。
除了在应用时以使用extends限定符,在定义泛型时也可以使用extends限定符,并且可以指定多个边界
普通方法,构造方法和静态方法中都可以使用泛型,编译器也不允许创建类型变量的数组
也可以用类型变量表示异常,称为参数化的异常,可以可以用于方法的throws列表中,但是不能用于catch子句中
在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分开
?通配符比泛型T任意类型更有效
类型推断
1、只有一处调用一个类型,或者多处调用同一个类型,推断出是当时这个类型
2、如果多处使用不同对象,并且没有返回值,取他们的交集
3、如果有返回值,优先考虑有返回值的类型
4、类型具有传递性
5、静态方法不能类泛型,要独立开单独类型
类加载器
java虚拟机安装多个类加载器,系统默认三个主要类加载器,每个类负载加载特定位置的类: BootStrap,ExtClassLoader,AppClassLoader
类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这个是BootStrap
java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象,需要为其指定一个父级装载器对象或者默认采用系统类装载器为其父级类加载
类加载器之间的父子关系和管辖范围
BootStrap<-ExtClassLoader<-AppClassLoader
BootStrap->JRE/lib/rt.jar
ExtClassLoader->JRE/lib/ext/*.jar
AppClassLoader(System classLoader)->ClASSPATH指定的所有jar或目录
类加载器的委托(子类交给父类)
代理
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常、日志、计算方法的运用时间,事物等。
采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类。
AOP
交叉业务的编程问题即为面向方面的编程(AOP)
AOP目标就是要使交叉业务模块化,可以采用将切换面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。
动态代理技术
JVM可以在运行时动态生出类的字节码,这种动态生成的类往往被称作代理类,即动态代理类。
JVM生成的动态类必须实现一个或者多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,可以使用CGLIB库。
代理类的各种方法中通常除了要调用目标相应方法和对外返回的结果外,还可以在代理方法中加上系统功能代码。
调用代理对象时,从Object类中继承hashCode,equals,或toString这几个方法,代理对象将调用请求转发给
InvocationHanderler对象,对于其他方法,则不转发调用请求。
实现AOP功能的封装与配制
工厂类BeanFactory负责创建目标类的实现类或代理类的实例对象,并通过配制文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配制文件中对应的类名不是ProxyFactyBean,则返回类的实例圣像,否则,
返回该类的实例对象的getProxy方法返回的对象。
BeanFactory的方法接收代表配制文件的输入流对象。
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供目标和通知信息。
编写客户端应用,实现Advice接口类和在配制文件中进行配置,调用BeanFactory获取对象。
jdk1.5 新特征
1。静态导入
它实现将类中的静态方法导入文件中,例如import static java.lang.Math.*;
2。可变参数(一个方法接受的参数个数不固定)
只能出现在参数列表的最后;
...位于变量类型的变量名之间,前后有无空格都可以;
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
int... is它类似 int[] is,使用时可以数组的形式访问
3。增强for循环
for(type 变量名:集合变量){...}
迭代变量必须在()中定义
集合变量可以是数组或者实现了Iterable接口的集合类
4。基本数据类型的自动拆箱与装箱
自动装箱:Integer num =1; (多个装箱只能转换一个字节-128~127转换成同一个int类型对象,即享元模式:多个对象共享)
自动拆箱:System.out.println(num + 10);
5。枚举(enum)
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错,枚举
可以让编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目录。
a.枚举就相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。
b.枚举元素必须位于枚举体中的最开始部分,枚举元素列表后要有分号与其它成员变量分隔。
c.带构造方法的枚举:构造方法必须定义成私有的,如果多个构造方法,默认是空构造方法();
d.带方法的枚举:每个元素分别由枚举的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义
f.枚举只有一个成员时,就可以作为一种单例的实现方式
实例:
package cn.com;
public class EnumTest {
public static void main(String args[]){
WeekDay wd = WeekDay.MON;
System.out.println(wd);
System.out.println(wd.name());
System.out.println(wd.ordinal());
System.out.println(wd.valueOf("SAT").toString());
System.out.println(wd.values().length);
TrafficLamp tr =TrafficLamp.RED;
System.out.println(tr.nextLamp());
}
public enum WeekDay{
SUM,MON(),TUS(0),WED(1),THI,FRI,SAT;
private WeekDay(){
System.out.println("first");
}
private WeekDay(int day){
System.out.println("second");
}
}
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp() {
return GREEN;
}
},
GREEN(10){
public TrafficLamp nextLamp() {
return YELLOW;
}
},
YELLOW(30){
public TrafficLamp nextLamp() {
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){
this.time = time;
}
}
}
反射 (jdk 1.2后具有的特性)
反射的基石-》classs 类
1.java程序中的各个java类属于同一个类事物,描述这类名就是Class.
2.获取字节码的方式:
类名class,例如:System.class
对象.getClass(),例如:new Date().getClass();
Class.forName("类名"),例如:ClassName.forname("java.util.Date");
反射就是把java类中的各种成分映射成相应的java类。
Constructor类
getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法,newInstance() 创建此 Class 对象所表示的类的一个新实例
Field类
Field类代表某个类中的一个成员变量
Method类
Method类代表某个类中的一个成员方法
invoke(null,Class<?>);如果参数是null表示一个静态方法
Arrays.asList(Object);将数组对象转换成Array
演示例如:
package cn.com;
public class ReflectPoint {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "babbling";
public String str3 = "China";
public ReflectPoint(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "str1="+str1+" str2="+str2+" str3="+str3;
}
}
package cn.com;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
public class ReflectTest {
public static void main(String arg[]) throws Exception{
String str1 = "abc";
Class<? extends String> cls1 = str1.getClass();
Class<String> cls2 = String.class;
Class<?> cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
System.out.println(cls1.isPrimitive()); //是否是一个基本类型
System.out.println(int.class.isPrimitive());
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
System.out.println(int[].class.isPrimitive());
System.out.println(int[].class.isArray());
Constructor<String> cons = String.class.getConstructor(StringBuffer.class);
String str2 = (String)cons.newInstance(new StringBuffer("abc"));
System.out.println(str2);
System.out.println(str2.charAt(2));
ReflectPoint p1 = new ReflectPoint(2,4);
Field y = p1.getClass().getField("y");
System.out.println(y.get(p1));
Field x = p1.getClass().getDeclaredField("x");
x.setAccessible(true);
System.out.println(x.get(p1));
changeStringValue(p1);
System.out.println(p1);
//str1.charAt(1);
Method methodCharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str1, 1));
System.out.println(methodCharAt.invoke(str1, new Object[]{0}));
String starting = arg[0];
Method mainMethod = Class.forName(starting).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"abc","bcd"}});
int[] a1 = new int[]{1,2,3};
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[]{"abc","bcd","efg"};
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
Object object1 = a1;
Object object2 = a2;
Object object3[] = a3;
Object object4[] = a4;
// Object object5[] = a1;
System.out.println(object1+" "+object2+" "+object3+" "+object4);
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));
printObject(a1);
printObject(a4);
}
private static void printObject(Object obj) {
if(obj.getClass().isArray()){
for(int i=0;i<Array.getLength(obj);i++){
System.out.println(Array.get(obj, i));
}
}
}
private static void changeStringValue(Object p1) throws IllegalArgumentException, IllegalAccessException {
Field[] fields = p1.getClass().getFields();
for(Field field : fields){
if(field.getType() == String.class){
String oldValue = (String) field.get(p1);
String newValue = oldValue.replace('b', 'a');
field.set(p1, newValue);
}
}
}
}
class TestMain{
public static void main(String args[]){
for(String str : args){
System.out.println(str);
}
}
}
2.集合类
HashSet储存时要hashCode、equals比较,保证储存的值不相同
当一个对象被存储进Hashset集合中以后,就不能修改这个对象中的那些参与
计算哈希值的字段了,否则对象修改后的哈希值与最初存储存HashSet集合中时哈希值
就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去
HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet
集合中单独删除当前的对象,从而造成内在泄露。
反射的作用-》实现框架功能
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
演示例如:
package cn.com;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
public class ReflectTest1 {
public static void main(String arg[]) throws Exception{
Collection collections = new ArrayList();
ReflectPoint rp1 = new ReflectPoint(3,3);
ReflectPoint rp2 = new ReflectPoint(5,5);
ReflectPoint rp3 = new ReflectPoint(3,3);
collections.add(rp1);
collections.add(rp2);
collections.add(rp3);
collections.add(rp1);
System.out.println(collections.size());
// InputStream in = new FileInputStream("config.properties");
// InputStream in = ReflectTest1.class.getClassLoader().getResourceAsStream("..\\config.properties");//类加载器
InputStream in = ReflectTest1.class.getResourceAsStream("..\\..\\..\\config.properties");
Properties proper = new Properties();
proper.load(in);
in.close();
String className = proper.getProperty("className");
collections = (Collection) Class.forName(className).newInstance();
// collections = new HashSet(); //hashCode、equals比较,保证储存的值不相同
collections.add(rp1);
collections.add(rp2);
collections.add(rp3);
collections.add(rp1);
System.out.println(collections.size());
rp1.y = 10;
collections.remove(rp1);
System.out.println(collections.size());
}
}
由内省引出JavaBean
JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合命名规则。
package cn.com;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class IntroSpectorTest {
public static void main(String[] args) throws Exception {
ReflectPoint pion = new ReflectPoint(3, 4);
String properyName = "x";
Object obj = getProperty(pion, properyName);
System.out.println(obj);
Object value =5;
setProperty(pion, properyName, value);
System.out.println(pion.getX());
System.out.println(BeanUtils.getProperty(pion, "x"));
BeanUtils.setProperty(pion,"x","8");
System.out.println(pion.getX());
BeanUtils.setProperty(pion,"brith.time","1000");
System.out.println(BeanUtils.getProperty(pion, "brith"));
PropertyUtils.setProperty(pion, "x", 10);
System.out.println(PropertyUtils.getProperty(pion, "x"));
}
private static void setProperty(Object pion, String properyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd2 = new PropertyDescriptor(properyName, pion.getClass());
Method setX = pd2.getWriteMethod();
setX.invoke(pion, value);
}
private static Object getProperty(Object pion, String properyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
/*PropertyDescriptor pd = new PropertyDescriptor(properyName, pion.getClass());
Method getX = pd.getReadMethod();
Object obj = getX.invoke(pion);*/
BeanInfo bean =Introspector.getBeanInfo(pion.getClass());
PropertyDescriptor[] pds = bean.getPropertyDescriptors();
Object obj = null;
for(PropertyDescriptor ps : pds){
if(ps.getName().equals(properyName)){
Method getX = ps.getReadMethod();
obj = getX.invoke(pion);
}
}
return obj;
}
}
注解 (jd1.5新特征)
注解相当一种标记,java编译器,开发工具和其它程序可以用来反射标记,标记可以在包,类,字段,方法参数以及局部变量上。
Deprecated //过期
Override //重写覆盖
SuppressWarnings //取消显示指定的编译器警告(@SuppressWarnings("deprecation"))
@Retention(RetentionPolicy.RUNTIME) //保存在运行时(CLASS 保留策略默认,SOURCE 编译器要丢弃的注释)
@Target(ElementType.METHOD) //限制在方法声明使用 {ElementType.METHOD,ElementType.TYPE} TYPE(包括Class Interface Enum等)
package cn.com;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Annotation {
String color() default "blue"; //= public abstract String color();
String value(); //value是个特殊的关键字,当只有value一个参数时,应用时可以不写value
int[] arrayAttr() default {2,3,4};
ElementType elem() default ElementType.TYPE;
MetaAnnotation metaAnnotation() default @MetaAnnotation("abc");
Class classes() default StringBuffer.class;
}
package cn.com;
@Annotation(classes=String.class,metaAnnotation=@MetaAnnotation("bgf"),color="red",value="abc",arrayAttr=2)//={1,2,3}
public class AnnotationTest {
@SuppressWarnings("deprecation")
@Annotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
new AnnotationTest().hello();
if(AnnotationTest.class.isAnnotationPresent(Annotation.class)){
Annotation annotation = AnnotationTest.class.getAnnotation(Annotation.class);
System.out.println(annotation);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr());
System.out.println(annotation.elem());
System.out.println(annotation.metaAnnotation().value());
System.out.println(annotation.classes());
}
}
@Deprecated
public void hello(){
System.out.println("你好!");
}
}
泛型(jd1.5新特征)
泛型是提供java编译器使用的,可以限定集合中的输入类型,使程序运行效果不受影响。
AarryList<E>类定义和ArraryList<Integer>类引用中涉及如下术语:
整个称为ArrayList<E>泛型类型
整个ArraryList<Integer>称为参数化的类型
ArraryList<Interge>中的Interge称为类型参数的实例或实际类型参数
ArraryList<Interge>中的<> typeof
ArraryList称为原始类型
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报警告
原始类型可以引用一个参数化类型的对象,编译报警告
参数化类型不考虑参数的继承关系
在创建数组实例时,数组的元素不能使用参数化的类型,如下
Vector<Integer> verctor[] = new Vector<Integer>[10];//错误写法
使用?通配符可以用其它各种参数化的类型,?通配符定义的变量主要作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
限定通配符的上下边界:
限定通配符的上边界:如 Vector<? extends Number> x = new Vector<Integer>();
限定通配符的下边界:如 Vector<? super Interger> x = new Vector<Number>();
提示:限定通配符总是包括自己
泛型中的T代表任意类型。
只有引用类型才有泛型方法的实际参数,基本类型是没有泛型的。
除了在应用时以使用extends限定符,在定义泛型时也可以使用extends限定符,并且可以指定多个边界
普通方法,构造方法和静态方法中都可以使用泛型,编译器也不允许创建类型变量的数组
也可以用类型变量表示异常,称为参数化的异常,可以可以用于方法的throws列表中,但是不能用于catch子句中
在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分开
?通配符比泛型T任意类型更有效
类型推断
1、只有一处调用一个类型,或者多处调用同一个类型,推断出是当时这个类型
2、如果多处使用不同对象,并且没有返回值,取他们的交集
3、如果有返回值,优先考虑有返回值的类型
4、类型具有传递性
5、静态方法不能类泛型,要独立开单独类型
package cn.com;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
public class GanericTest {
public static void main(String[] args) throws Exception {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
System.out.println(list.getClass() == list1.getClass());
list1.getClass().getMethod("add", Object.class).invoke(list1, "xyz");
System.out.println(list1.get(1));
printConllection(list);
printConllection(list1);
Class<? super String> str = String.class.getSuperclass();
System.out.println(str);
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("张三", 20);
map.put("李四", 21);
map.put("王五", 22);
Set<Map.Entry<String,Integer>> set =map.entrySet();
for(Map.Entry<String,Integer> entry : set){
System.out.println("key = "+entry.getKey()+" value = "+entry.getValue());
}
add(3,5);
Number x1 = add(3.5,3);
Object x2 = add(3,"abc");
swap(new String[]{"abc","def","ghi"},1,2);
Object obj ="abc";
String x3 = autoConvert(obj);
copy1(new Vector<String>(),new String[10]);
copy2(new Date[10], new String[10]);
//copy1(new Vector<Date>(),new String[10]);
//Vector v1 = new Vector<Date>();
Method applyMethod = GanericTest.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]);
}
private static <T> T autoConvert(Object obj) {
return (T)obj;
}
private <T> void fillArrary(T[] a,T obj){
for(T t : a){
t = obj;
}
}
private static <T> void swap(T[] a, int i, int j) {
T temp = a[i];
a[i] = a[j];
a[j] =temp;
}
private static <T>T add(T i, T j) {
return j;
}
private static void printConllection(ArrayList<?> list) {
for(Object obj : list){
System.out.println(obj);
}
}
private static <T> void printConllection2(ArrayList<T> list) {
for(Object obj : list){
System.out.println(obj);
}
}
private static <T> void copy1(Collection<T> dest,T[] src){
for(T a : src){
dest.add(a);
}
}
private static <T> void copy2(T[] dest, T[] src){
for(int i=0; i<src.length; i++){
dest[i] = src[i];
}
}
public static void applyVector(Vector<Date> v){
}
}
类加载器
java虚拟机安装多个类加载器,系统默认三个主要类加载器,每个类负载加载特定位置的类: BootStrap,ExtClassLoader,AppClassLoader
类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这个是BootStrap
java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象,需要为其指定一个父级装载器对象或者默认采用系统类装载器为其父级类加载
类加载器之间的父子关系和管辖范围
BootStrap<-ExtClassLoader<-AppClassLoader
BootStrap->JRE/lib/rt.jar
ExtClassLoader->JRE/lib/ext/*.jar
AppClassLoader(System classLoader)->ClASSPATH指定的所有jar或目录
类加载器的委托(子类交给父类)
package cn.com;
import java.util.Date;
public class ClassLoaderAttachment extends Date{
@Override
public String toString() {
return "hello ClassLoaderAttachment";
}
}
package cn.com;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MyClassLoader extends ClassLoader {
private String classDir;
public MyClassLoader(){
}
public MyClassLoader(String classDir){
this.classDir = classDir;
}
public static void main(String args[]) throws Exception{
String srcPath = args[0];
String destDir = args[1];
FileInputStream fis = new FileInputStream(srcPath);
destDir +="\\"+srcPath.substring(srcPath.lastIndexOf("\\")+1);
FileOutputStream fos = new FileOutputStream(destDir);
cypher(fis, fos);
fis.close();
fos.close();
}
private static void cypher(InputStream ips, OutputStream ops) throws IOException{
int b = -1;
while((b = ips.read())!= -1){
ops.write(b ^ 0xff);
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classPath = classDir + "\\" +name.substring(name.lastIndexOf(".")+1)+".class";
try {
FileInputStream fis = new FileInputStream(classPath);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
cypher(fis, bout);
fis.close();
byte[] bytes = bout.toByteArray();
return defineClass(bytes, 0, bytes.length); //生成字节数组
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassFormatError e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
package cn.com;
import java.util.Date;
public class ClassLoaderTest {
public static <ClassLoaderAttachment> void main(String[] args) throws Exception {
System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
while(loader != null){
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
System.out.println(loader);
//System.out.println(new ClassLoaderAttachment());
Class clazz = new MyClassLoader("Loader").loadClass("cn.com.ClassLoaderAttachment");
Date d1 = (Date) clazz.newInstance();
System.out.println(d1);
}
}
代理
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常、日志、计算方法的运用时间,事物等。
采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类。
AOP
交叉业务的编程问题即为面向方面的编程(AOP)
AOP目标就是要使交叉业务模块化,可以采用将切换面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。
动态代理技术
JVM可以在运行时动态生出类的字节码,这种动态生成的类往往被称作代理类,即动态代理类。
JVM生成的动态类必须实现一个或者多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,可以使用CGLIB库。
代理类的各种方法中通常除了要调用目标相应方法和对外返回的结果外,还可以在代理方法中加上系统功能代码。
调用代理对象时,从Object类中继承hashCode,equals,或toString这几个方法,代理对象将调用请求转发给
InvocationHanderler对象,对于其他方法,则不转发调用请求。
package cn.com;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod();
void afterMethod(Method method);
}
package cn.com;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long starttime = 0;
@Override
public void beforeMethod() {
starttime = System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
long endtime = System.currentTimeMillis();
System.out.println(method + " 发费时间:" + (endtime - starttime));
}
}
package cn.com;
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 {
public static void main(String args[]) throws Exception{
Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy.getName());
System.out.println("-----begin constuctor------");
Constructor[] constraints = clazzProxy.getConstructors();
for(Constructor constructor : constraints){
String name = constructor.getName();
StringBuffer sBuffer = new StringBuffer(name);
sBuffer.append("(");
Class[] classParams = constructor.getParameterTypes();
for(Class classparam : classParams){
sBuffer.append(classparam.getName()+" "+
classparam.getName().substring(classparam.getName().lastIndexOf(".")+1,
classparam.getName().length()).toString().toLowerCase()).append(',');
}
if(classParams.length>0){
sBuffer.deleteCharAt(sBuffer.length()-1);
}
sBuffer.append(")");
System.out.println(sBuffer);
}
System.out.println("-----begin method------");
Method[] methods = clazzProxy.getMethods();
for(Method method : methods){
String name = method.getName();
StringBuffer sBuffer = new StringBuffer(name);
sBuffer.append("(");
Class[] classParams = method.getParameterTypes();
for(Class classparam : classParams){
sBuffer.append(classparam.getName()+" "+
classparam.getName().substring(classparam.getName().lastIndexOf(".")+1,
classparam.getName().length()).toString().toLowerCase()).append(',');
}
if(classParams.length>0){
sBuffer.deleteCharAt(sBuffer.length()-1);
}
sBuffer.append(")");
System.out.println(sBuffer);
}
System.out.println("-----begin create instance------");
Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);
class MyInvocationHander implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander());
proxy1.clear();
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
final ArrayList target = new ArrayList();
Collection proxy3 = (Collection) getProxy(target,new MyAdvice());
proxy3.add("abc");
proxy3.add("xyz");
System.out.println(proxy3.size());
}
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/* new Class[]{Collection.class},*/
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*long starttime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endtime = System.currentTimeMillis();
System.out.println(method + " 发费时间:" + (endtime - starttime));
return retVal;*/
advice.beforeMethod();
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
实现AOP功能的封装与配制
工厂类BeanFactory负责创建目标类的实现类或代理类的实例对象,并通过配制文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配制文件中对应的类名不是ProxyFactyBean,则返回类的实例圣像,否则,
返回该类的实例对象的getProxy方法返回的对象。
BeanFactory的方法接收代表配制文件的输入流对象。
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供目标和通知信息。
编写客户端应用,实现Advice接口类和在配制文件中进行配置,调用BeanFactory获取对象。
package cn.com;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
Properties props = new Properties();
public BeanFactory(InputStream ips){
try {
props.load(ips);
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name){
String className = props.getProperty(name);
Object bean = null;
try {
Class clazz = Class.forName(className);
bean = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean){
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
Object proxy = null;
try {
Advice advice = (Advice) Class.forName(props.getProperty(name + ".advice")).newInstance();
Object target = Class.forName(props.getProperty(name + ".target")).newInstance();
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
proxy = ((ProxyFactoryBean)bean).getProxy();
} catch (Exception e) {
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
package cn.com;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean {
private Object target;
private Advice advice;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getProxy() {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/* new Class[]{Collection.class},*/
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*long starttime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endtime = System.currentTimeMillis();
System.out.println(method + " 发费时间:" + (endtime - starttime));
return retVal;*/
advice.beforeMethod();
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
package cn.com;
import java.io.InputStream;
import java.util.Collection;
public class AopFrameworkTest {
public static void main(String[] args) {
InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
((Collection)bean).clear();
}
}