Java学习笔记

2011-7-9
可变参数特点:
(1) 只能出现在参数列表的最后;
(2) …位于变量类型和变量名之间,前后有无空格都可以。
(3) 调用可变参数时,编译器为该可变参数隐含创建一个数组,在方法题中以数组的形式访问可变参数。

-128~127之间的int自动装箱成Integer,编译器会给他创建缓存,若干个这样的值一样的Integer就是一个对象。
这就是享元模式:如果很多很小的对象,他们有很多相同的东西,那么就可以把它们变成一个对象,把不同的东西做为外部属性作为方法的参数传入。

枚举就是要规定给类型赋的值必须是开始指定好的值。

如何得到各个字节码对应的实例对象(Class类型)
(1) 类名.class,例如,System.class
(2) 对象.getClass(),例如new Date().getClass()
(3) Class.forName(“类名”),例如,Class.forName(“java.util.Date”);\

只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[] , void

反射就是把Java类中的各种成分映射成相应的Java类。

构造方法的反射应用:
(1)获得方法时要用到类型。
(2)调用获得的方法时要用到上面相同类型的实例对象。

反射会导致程序性能的下降。

暴力反射:不管变量是否可见,直接取。
Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));

为什么要用反射的方式执行某个类中的main()方法?因为一开始不知道类的名字。

2011-7-10
(1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,他们的哈希码也必须相等,但反之则不成立,即equals方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较的结果可以不等,例如字符串:“BB”和“Aa”的equals方法比较结果肯定不相等,但他们的hashCode方法返回值却相等。
(2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法是用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏。

框架要解决的核心问题:因为在写程序时无法知道要被调用的类名,所以,在程序中无法直接new某个对象的实例了,而要用反射的方式做。

JavaBean是一种特殊的Java类,他的方法名必须符合特定的规则(getXxx(), SetXxx())。

注解相当于一种标记,在程序中嫁了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序就可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

泛型:
没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样更方便。

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如,用反射得到集合,再调用其add方法即可。

参数化类型不考虑类型参数的集成关系:
Vector<String> v = new Vector<Object>();  //错误//不写<Object>没错,写了就是明知故犯
Vector<Object> v = new Vector<String>();  //也错误
Vecctor v1 = new Vector<String>(); Vector<Object> v = v1;  //这样没错。。

使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

Java中的泛型类型(或者泛型)类似于C++中的模板。但是这种相似性仅限于表面,Java语言中的泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术成为擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为Java厂商升级其JVM造成难以逾越的障碍。所以,Java的泛型采用了可以完全在编译器中实现的擦除方法。

只有引用类型才能作为泛型方法的实际参数

某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最小并集类型(张老师说是最大交集,错了,同样也应是最小公倍数)。

在对泛型类型进行参数化时,类型参数的实力必须是引用类型,不能是基本类型。
当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该拥有类级别的类参数。

类加载器的委托机制:
首先当线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来制定某个类加载器去加载某个类。


每个类加载器加载类时,又先委托给其上级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的/itcast.jar包中后,运行结果为ExtClassLoader的原因。

你可能感兴趣的:(Java学习)