java基础加强学习笔记
2011-02-27 21:28
387 查看
学习了Eclipse的一些使用,
静态导入,
可变参数方法,(int i, int... args){}(可变参数必须是最后一个参数,以数组的形式来访问可变参数)
for循环加强形式(foreach),
基本数据类型的自动装箱和拆箱,如果数值在一个字节之内(-128~127之间的数值),那么这个数值会缓存起来,如果下一次同样的数据需要装箱,那么就直接拿这一份数据来用。
比如:Integer i = 23; Integer j = 23; 那么 i==j;如果Integer i = 128; Integer j = 128; 那么 i!=j; (享元模式:很多小的对象,有很多相同的属性的时候,可以考虑使用享元模式。不同的属性就设为方法的参数传进来,叫外部属性或外部状态。)
枚举类的学习,枚举里面的每一个元素都是一个类的实际对象。如:
public enum WeekDate {
SUN(1),MON,TUE; //没指定参数列表的时候调用无参数的构造方法,指定了参数就调用对应的构造方法。
private WeekDate(){} //构造方法必须是私有的。
private WeekDate(int day){}
}
实现带有抽象方法的枚举
枚举只有一个成员时,就可以作为一种单例的实现方式。
Class类的使用。
得到字节码(Class类)的方式有三种:
类名.class;
对象名.getClass();
Class.forName("类名");
有9个预定义的Class实例对象(8个基本数据类型和void)。
int.class = Integer.TYPE;
int.class.isPrimitive();-----true //判断class类是否为基本数据类型。
int[].class.isArray();-----true //判断Class类是否为数组类。
理解了反射的概念,构造方法的反射应用,成员变量的反射,成员方法的反射(静态方法的反射调用时,对象的值可以是null,如:methodTest.invoke(null, "hello")),
对接收数组参数的成员方法进行反射的2种解决方案:new Object(arrays[]),(object)arrays[]。
数组类型:如果有相同的维数和相同的类型,他们就同一份字节码,即同一个Class类。
Array工具类用于完成对数组的反射操作,如:Array.getLength(obj); Array.get(obj, index);
温习了ArrayList与HashSet的比较,学习了Hashcode的分析,按照Hash算法存储的内存分配是按区域来算的,效率高。equals与hashcode方法的适当使用。
**有一个问题得注意:当一个对象被存储进HashSet集合之后,就不能修改这个对象中那些参与计算哈希值的字段,否则,对象修改后的哈希值与最初存储进HashSet时的哈希值就不同了,
在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将找不到对象,这将导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏。
通过简单的案例温习了反射技术开发框架的原理(扩展:流类之所以需要使用后调用close()关闭流,释放系统资源。这个java本身的垃圾回收机制是两回事,java垃圾回收机制是回收java本身的垃圾对象内存,而调用
close()是释放对象关联的系统资源。)
用类加载器加载资源文件this.class.getClassLoader().getResourceAsStream(path)/this.class.getResourceAsStream(path);
javaBean的简单介绍。JDK提供了对JavaBean进行操作的一些API,这套API称为内省。
对JavaBean的简单内省操作:java.beans.PropertyDescriptor属性描述符类。new PropertyDescriptor(propertyName, class);
对JavaBean的复杂内省操作:java.beans.Introspector.getBeanInfo(class);这种方法复杂一些。
使用BeanUtils工具包操作JavaBean,需下载和导入beanutils和logging包。使用BeanUtils操作JavaBeam方便快捷。
BeanUtils的setProperty()和getProperty()方法支持属性的级联。如:BeanUtils.setProperty(pt1, "birthday.time", "111");因为示例类中的birthday属性是属于Date类型,而Date类有一个方法为setTime(),所以级联属性为birthday.time可以设置其中的值。BeanUtils类还可以操作Map类(key-value)。
另外还有一个类PropertyUtils的功能和BeanUtils功能差不多,但是BeanUtils是以字符串的形式对值进行操作,但是PropertyUtils是以属性本身的类型进行操作。
了解了注解和入门注解的应用。注解的定义与反射调用。Class类中的isAnnotationPresent(),getAnnotation()的用法。Retention元注解描述注解的生命周期,Target元注解描述注解的所适用的程序元素的种类,如:TYPE,METHOD,FIELD等。
(扩展:class文件并不是一份字节码,当类加载到内存以后的二进制码才叫字节码。)
一个注解的生命周期有三个阶段:RetentionPolicy.CLASS(class文件阶段), RetentionPolicy,RUNTIME(内存中的字节码阶段), RetentionPolicy.SOURCE(源文件阶段),RetentionPolicy是枚举类。
学习了为注解增加属性,定义的时候是方法的形式(String color();),赋值的时候是属性的形式(color="red"),读取的时候还是用方法的形式调用(.color())。
如果只有一个属性需要指定,并且这个属性名字是value,那么赋值的时候可以省略“属性名=”,直接("属性值")即可。
定义属性的时候可以指定缺省的默认值,如:String color() default "blue";
学习了为注解增加各种属性。如数组,枚举,甚至是注解。
使用泛型,首先的一个好处是避免强制类型转换。
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型信息,所以只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据。例如:用反射得到集合,再调用其add()方法即可。如:collection1.getClass().getMethod("add", Object.class).invoke(collection1, "haha");
注意:以下语句合法:Collection<String> c = new Vector(); Collection c = new Vector<String>();
在创建数组实例时,数组的元素不能使用参数化的类型,例如下面的语句是错误的:Vector<Integer> vectorList[] = new Vector<Integer>[10];
泛型的通配符是“?”,使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
泛型通配符的扩展:Vector<? extends Number> v = new Vector<Integer>(); Vector<? super Integer> v = new Vector<Number>();
通过泛型集合的综合案例学习了Map.Entry的使用。Map中有一个方法entrySet()将返回一个Set集合,里面放置了Map.Entry,里面是key-value对,Map.Entry中的常用方法getKey(),getValue();
自定义泛型方法及应用。如:
private static <T> T add(T x, T y) {
return null;
}
如果是泛型的加法,将返回的值是各个加数的类型的交集的类型,如:add(2, "hello")将返回Object对象,Obj
4000
ect result = add(2, "hello");
下面是实现数组中两个元素值的交换:
private static <T> void swap(T[] a, int i, int j) {
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
注意:只有引用类型才能作为泛型方法的实际参数,如swap(new String[]{"a", "b", c}, 0, 1);是没问题的,但是:swap(new int[]{1, 2, 3}, 0, 1);是不能通过编译的。
除了在应用泛型是可以使用extends限定符,在定义泛型时也可以使用extends限定符,例如:Class.getAnnotation()方法的定义,并且可以使用&符号来指定多个边界,如
<V extends Serializable & cloneable> void method() {}。
我们也可以用类型变量表示异常,称为参数化异常,可以用于方法的throws 列表中,但是不能用于catch()字句中。
在泛型中,可以同时有多个类型参数,在定义他们的尖括号中用“,”分隔,例如:public static <K, V> V getValue(K key) {return map.get(key);}
下面方法可以将Object的类型转换为任何类型: //此方法很有趣,可以根据他的返回值类型自动转换。
public static <T> T autoConvert(Object obj) {
return (T)obj;
}
如:Object o = "aaa";
String str = autoConvert(o); //因为此语句返回值类型是String,所以可以根据他的返回值类型自动转换return (T)obj;这个(T)就是将obj强制转换成跟返回值一样的类型。
学习了自定义泛型类的应用。
类里面的静态成员不能使用泛型类型的变量。
学习了通过反射获得泛型的实际类型参数。主要代码如下:(GenericTest类是自定义的示例类)
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]);
public static void applyVector(Vector<Date> v1){}
其中原理:不能通过集合对象本身获取,只能通过反射的方法进行取得。
类加载器之间的父子关系:BootStrap(爷)------ExtClassLoader(父)-----AppClassLoader(子)
注意:BootStrap不是一个java类,是直接在虚拟机里面的一个加载器。其他两个加载器都是java类。
BootStrap加载JRE/lib/rt.jar里面的类
ExtClassLoader加载JRE/lib/ext/*.jar里面的类
AppClassLoader加载classpath指定的所有jar或目录里面的类
我们还可以写自己的类加载器去加载指定的特殊的目录
(自定义的类加载器必须继承ClassLoader,loadClass()方法和findClass()方法,difineClass()方法)
类加载器的委托机制:从子类开始委托,一直到爷爷祖先类,也就是说先让BootStrap加载,找不到的话再让ExtClassLoader加载,再找不到的话就让AppClassLoader加载,再找不到的话
就让自定义类加载器加载。。。
(扩展:模版方法设计模式:父类loadClass/findClass-----子类1,子类2,子类3。。。)
(有包名的类不能调用无包名的类!)
学习了自己编写的解密类加载器。
学习了类加载器的一个高级问题的实验分析。(如果A类用到了B类,那么B类由加载A类的加载器去加载。)
学习了代理类的作用与原理和AOP概念(面向方面编程:目标就是要使交叉业务模块化)。
只要是面向方面的编程就涉及到代理。
JVM(Java虚拟机)可以在运行期动态生成出类的字节码,这种动态生成的类往往被用过代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果目标类没有实现接口,要想生成他的代理,那么就用CGLIB库(第三方类库,不是JAVA标准),CGLIB可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果
要为一个没有实现接口的类生成动态代理类,那么就用CGLIB库。
(扩展:StringBuilder与StringBuffer的区别:他们都是可变的字符序列,
不同的是在单线程编程里面用StringBuilder效率要高一些,因为StringBuilder不用考虑线程安全,而多线程里面要考虑线程安全的话就使用StringBuffer);
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); //动态代理类的生成示例。
学习了创建动态类的实例对象及调用其方法。
完成InvocationHandler对象的内部功能,主要就是要重写
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}这个方法。
学习了InvocationHandler对象的运行原理
让动态生成的类成为目标类的代理。
学习了动态代理类的设计原理与结构
学习了编写可生成代理和插入通告的通用方法(主要是传一个目标和编写实现系统功能的对象进去。)
学习了实现类似spring的可配置的AOP框架
(扩展:JavaBean必须要有一个不带参数的构造方法。)
静态导入,
可变参数方法,(int i, int... args){}(可变参数必须是最后一个参数,以数组的形式来访问可变参数)
for循环加强形式(foreach),
基本数据类型的自动装箱和拆箱,如果数值在一个字节之内(-128~127之间的数值),那么这个数值会缓存起来,如果下一次同样的数据需要装箱,那么就直接拿这一份数据来用。
比如:Integer i = 23; Integer j = 23; 那么 i==j;如果Integer i = 128; Integer j = 128; 那么 i!=j; (享元模式:很多小的对象,有很多相同的属性的时候,可以考虑使用享元模式。不同的属性就设为方法的参数传进来,叫外部属性或外部状态。)
枚举类的学习,枚举里面的每一个元素都是一个类的实际对象。如:
public enum WeekDate {
SUN(1),MON,TUE; //没指定参数列表的时候调用无参数的构造方法,指定了参数就调用对应的构造方法。
private WeekDate(){} //构造方法必须是私有的。
private WeekDate(int day){}
}
实现带有抽象方法的枚举
枚举只有一个成员时,就可以作为一种单例的实现方式。
Class类的使用。
得到字节码(Class类)的方式有三种:
类名.class;
对象名.getClass();
Class.forName("类名");
有9个预定义的Class实例对象(8个基本数据类型和void)。
int.class = Integer.TYPE;
int.class.isPrimitive();-----true //判断class类是否为基本数据类型。
int[].class.isArray();-----true //判断Class类是否为数组类。
理解了反射的概念,构造方法的反射应用,成员变量的反射,成员方法的反射(静态方法的反射调用时,对象的值可以是null,如:methodTest.invoke(null, "hello")),
对接收数组参数的成员方法进行反射的2种解决方案:new Object(arrays[]),(object)arrays[]。
数组类型:如果有相同的维数和相同的类型,他们就同一份字节码,即同一个Class类。
Array工具类用于完成对数组的反射操作,如:Array.getLength(obj); Array.get(obj, index);
温习了ArrayList与HashSet的比较,学习了Hashcode的分析,按照Hash算法存储的内存分配是按区域来算的,效率高。equals与hashcode方法的适当使用。
**有一个问题得注意:当一个对象被存储进HashSet集合之后,就不能修改这个对象中那些参与计算哈希值的字段,否则,对象修改后的哈希值与最初存储进HashSet时的哈希值就不同了,
在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将找不到对象,这将导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏。
通过简单的案例温习了反射技术开发框架的原理(扩展:流类之所以需要使用后调用close()关闭流,释放系统资源。这个java本身的垃圾回收机制是两回事,java垃圾回收机制是回收java本身的垃圾对象内存,而调用
close()是释放对象关联的系统资源。)
用类加载器加载资源文件this.class.getClassLoader().getResourceAsStream(path)/this.class.getResourceAsStream(path);
javaBean的简单介绍。JDK提供了对JavaBean进行操作的一些API,这套API称为内省。
对JavaBean的简单内省操作:java.beans.PropertyDescriptor属性描述符类。new PropertyDescriptor(propertyName, class);
对JavaBean的复杂内省操作:java.beans.Introspector.getBeanInfo(class);这种方法复杂一些。
使用BeanUtils工具包操作JavaBean,需下载和导入beanutils和logging包。使用BeanUtils操作JavaBeam方便快捷。
BeanUtils的setProperty()和getProperty()方法支持属性的级联。如:BeanUtils.setProperty(pt1, "birthday.time", "111");因为示例类中的birthday属性是属于Date类型,而Date类有一个方法为setTime(),所以级联属性为birthday.time可以设置其中的值。BeanUtils类还可以操作Map类(key-value)。
另外还有一个类PropertyUtils的功能和BeanUtils功能差不多,但是BeanUtils是以字符串的形式对值进行操作,但是PropertyUtils是以属性本身的类型进行操作。
了解了注解和入门注解的应用。注解的定义与反射调用。Class类中的isAnnotationPresent(),getAnnotation()的用法。Retention元注解描述注解的生命周期,Target元注解描述注解的所适用的程序元素的种类,如:TYPE,METHOD,FIELD等。
(扩展:class文件并不是一份字节码,当类加载到内存以后的二进制码才叫字节码。)
一个注解的生命周期有三个阶段:RetentionPolicy.CLASS(class文件阶段), RetentionPolicy,RUNTIME(内存中的字节码阶段), RetentionPolicy.SOURCE(源文件阶段),RetentionPolicy是枚举类。
学习了为注解增加属性,定义的时候是方法的形式(String color();),赋值的时候是属性的形式(color="red"),读取的时候还是用方法的形式调用(.color())。
如果只有一个属性需要指定,并且这个属性名字是value,那么赋值的时候可以省略“属性名=”,直接("属性值")即可。
定义属性的时候可以指定缺省的默认值,如:String color() default "blue";
学习了为注解增加各种属性。如数组,枚举,甚至是注解。
使用泛型,首先的一个好处是避免强制类型转换。
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型信息,所以只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据。例如:用反射得到集合,再调用其add()方法即可。如:collection1.getClass().getMethod("add", Object.class).invoke(collection1, "haha");
注意:以下语句合法:Collection<String> c = new Vector(); Collection c = new Vector<String>();
在创建数组实例时,数组的元素不能使用参数化的类型,例如下面的语句是错误的:Vector<Integer> vectorList[] = new Vector<Integer>[10];
泛型的通配符是“?”,使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
泛型通配符的扩展:Vector<? extends Number> v = new Vector<Integer>(); Vector<? super Integer> v = new Vector<Number>();
通过泛型集合的综合案例学习了Map.Entry的使用。Map中有一个方法entrySet()将返回一个Set集合,里面放置了Map.Entry,里面是key-value对,Map.Entry中的常用方法getKey(),getValue();
自定义泛型方法及应用。如:
private static <T> T add(T x, T y) {
return null;
}
如果是泛型的加法,将返回的值是各个加数的类型的交集的类型,如:add(2, "hello")将返回Object对象,Obj
4000
ect result = add(2, "hello");
下面是实现数组中两个元素值的交换:
private static <T> void swap(T[] a, int i, int j) {
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
注意:只有引用类型才能作为泛型方法的实际参数,如swap(new String[]{"a", "b", c}, 0, 1);是没问题的,但是:swap(new int[]{1, 2, 3}, 0, 1);是不能通过编译的。
除了在应用泛型是可以使用extends限定符,在定义泛型时也可以使用extends限定符,例如:Class.getAnnotation()方法的定义,并且可以使用&符号来指定多个边界,如
<V extends Serializable & cloneable> void method() {}。
我们也可以用类型变量表示异常,称为参数化异常,可以用于方法的throws 列表中,但是不能用于catch()字句中。
在泛型中,可以同时有多个类型参数,在定义他们的尖括号中用“,”分隔,例如:public static <K, V> V getValue(K key) {return map.get(key);}
下面方法可以将Object的类型转换为任何类型: //此方法很有趣,可以根据他的返回值类型自动转换。
public static <T> T autoConvert(Object obj) {
return (T)obj;
}
如:Object o = "aaa";
String str = autoConvert(o); //因为此语句返回值类型是String,所以可以根据他的返回值类型自动转换return (T)obj;这个(T)就是将obj强制转换成跟返回值一样的类型。
学习了自定义泛型类的应用。
类里面的静态成员不能使用泛型类型的变量。
学习了通过反射获得泛型的实际类型参数。主要代码如下:(GenericTest类是自定义的示例类)
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]);
public static void applyVector(Vector<Date> v1){}
其中原理:不能通过集合对象本身获取,只能通过反射的方法进行取得。
类加载器之间的父子关系:BootStrap(爷)------ExtClassLoader(父)-----AppClassLoader(子)
注意:BootStrap不是一个java类,是直接在虚拟机里面的一个加载器。其他两个加载器都是java类。
BootStrap加载JRE/lib/rt.jar里面的类
ExtClassLoader加载JRE/lib/ext/*.jar里面的类
AppClassLoader加载classpath指定的所有jar或目录里面的类
我们还可以写自己的类加载器去加载指定的特殊的目录
(自定义的类加载器必须继承ClassLoader,loadClass()方法和findClass()方法,difineClass()方法)
类加载器的委托机制:从子类开始委托,一直到爷爷祖先类,也就是说先让BootStrap加载,找不到的话再让ExtClassLoader加载,再找不到的话就让AppClassLoader加载,再找不到的话
就让自定义类加载器加载。。。
(扩展:模版方法设计模式:父类loadClass/findClass-----子类1,子类2,子类3。。。)
(有包名的类不能调用无包名的类!)
学习了自己编写的解密类加载器。
学习了类加载器的一个高级问题的实验分析。(如果A类用到了B类,那么B类由加载A类的加载器去加载。)
学习了代理类的作用与原理和AOP概念(面向方面编程:目标就是要使交叉业务模块化)。
只要是面向方面的编程就涉及到代理。
JVM(Java虚拟机)可以在运行期动态生成出类的字节码,这种动态生成的类往往被用过代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果目标类没有实现接口,要想生成他的代理,那么就用CGLIB库(第三方类库,不是JAVA标准),CGLIB可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果
要为一个没有实现接口的类生成动态代理类,那么就用CGLIB库。
(扩展:StringBuilder与StringBuffer的区别:他们都是可变的字符序列,
不同的是在单线程编程里面用StringBuilder效率要高一些,因为StringBuilder不用考虑线程安全,而多线程里面要考虑线程安全的话就使用StringBuffer);
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); //动态代理类的生成示例。
学习了创建动态类的实例对象及调用其方法。
完成InvocationHandler对象的内部功能,主要就是要重写
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}这个方法。
学习了InvocationHandler对象的运行原理
让动态生成的类成为目标类的代理。
学习了动态代理类的设计原理与结构
学习了编写可生成代理和插入通告的通用方法(主要是传一个目标和编写实现系统功能的对象进去。)
学习了实现类似spring的可配置的AOP框架
(扩展:JavaBean必须要有一个不带参数的构造方法。)
相关文章推荐
- 黑马程序员_java基础加强学习笔记之注解
- 黑马程序员—Java基础加强学习笔记之枚举&反射
- 黑马程序员_java基础加强学习笔记之(JDK1.5新特性)
- Java基础加强学习笔记(二)
- 黑马程序员---java学习笔记之java基础加强二
- 黑马程序员—Java基础加强学习笔记之泛型
- Java基础加强学习笔记
- 黑马程序员--Java基础加强学习笔记之重载和覆写、可变参数、枚举
- Java基础加强学习笔记
- Java学习笔记(Java基础加强学习)
- 黑马程序员--Java基础加强学习笔记之Class类、反射(Reflect)
- JAVA 基础加强学习笔记
- 超详细的java基础知识学习(java SE、javaEE)笔记 核心重点!
- JAVA语言基础 +JAVA学习笔记-DAY04
- 匿名内部类--毕向东java基础教程学习笔记
- 黑马程序员--Java基础加强(高新技术)学习第一天
- 集合1--毕向东java基础教程视频学习笔记
- java学习笔记(计算机基础知识)
- JAVA基础18天速成学习笔记之第二天
- JAVA基础18天速成学习笔记之第9天