[黑马程序员] 高新_枚举、反射、泛型、类加载器、动态代理 (五)

2014-11-24 10:33:32 · 作者: · 浏览: 4
tatic void main(String[] args) {
for(String arg: args){
System.out.println(arg);
}
}
}


public class Test3 {

public static void main(String[] args) throws Exception{

String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); //* 为了兼容JDK1.4, 会把传入的数组打散开. 这里就作为三个元素. 把数组强制转换成(Object)也行.
}

}

14. java.lang.reflect.Array类, 数组反射的应用:

同种元素数据类型, 且相同维度的数组, 反射来的类相同.

没有办法得到数组中元素的类型.


15. 其他:


看JDK的源代码方法:
找到D:\Program Files\Java\jdk1.7.0_09\src.zip压缩包, 打开, 按所属包名找到源文件即可.
Eclipse中直接Ctrl+左键点击类名即可跳转. 再Ctrl+O搜索想看的就行.
反射会导致程序性能严重下降.
Eclipse显示"生成源代码"相关列表的快捷键: Alt+Shift+S
* 暴力反射: 反射获取Field时, 对于可见的Field直接用getField(...)方法即可; 对于不可见的Field要使用getDeclaredField(..)获得Field对象, 然后调用Field对象的setAccessible(true)之后才能获取. 这叫做暴力反射.


泛型
16. 泛型应用的综合案例:

[java]
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

class Test2
{
public static void main(String [] args) throws Exception
{
HashMap maps = new HashMap();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);

Set> entrySet = maps.entrySet();
for(Map.Entry entry: entrySet){
System.out
.println(entry.getKey() + ":" + entry.getValue());
}

}
}

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

class Test2
{
public static void main(String [] args) throws Exception
{
HashMap maps = new HashMap();
maps.put("zxx", 28);
maps.put("lhm", 35);
maps.put("flx", 33);

Set> entrySet = maps.entrySet();
for(Map.Entry entry: entrySet){
System.out
.println(entry.getKey() + ":" + entry.getValue());
}

}
}


17. 自定义泛型方法:

[java]
return null;
}

private static add(T x,T y){
return null;
}上面的方法接受两个T型参数, 返回一个T型的值. (不能接受子类)
其中的T只能代表引用类型, 不能代表基本类型. 例如: T可以不能代替int,但可以代替由int自动装箱来的Integer.
用于放置泛型的类型参数的尖括号应出现在其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
伟大的Java还支持上限通配符< extends Type>, 表示必须是Type本身或其子类; 下限通配符< super Type>, 表示必须是Type本身或其父类.

类加载器
18. 类加载器也是Java类, 因为其他是Java类的类加载器本身也需要被类加载器加载, 所以一定存在一个最早的类加载器不是Java类, 这个类加载器就是BootStrap.


19. JVM中可以安装多个类加载器, 系统默认有三个主要的类加载器, 分别负责加载特定位置的类:


BootStrap: 加载JRE/lib/rt.jar中的类.* BootStrap不是Java类, 是在JVM内核中的用C++写的一段二进制代码.
ExtClassLoader: 加载JRE/lib/ext/*.jar中的类.
AppClassLoader: 加载CLASSPATH指定的所有jar或目录.


20. BootStrap是ExtClassLoader的父类, ExtCalssLoader是ApptClassLoader的父类.


21.* 类加载器的委托机制:
想要用一个类加载器加载一个类的时候, 这个加载器并不会直接去加载, 而是去调用它的父类类加载器去加载, 而父类加载器如果还有父类的话就继续调用, 直到BootStrap. 如果BootStrap能成功加载, 则加载, 否则向下找并尝试加载, 如果找到最初的那个类加载器还是不能完成加载的话, 则抛出ClassNotFoundException异常.


22. JVM要加载一个类时, 派出那个类去加载
首先当前线程的类加载器去加载线程中的第一个类. (可以通过getContextClassCloader()和setContextClassLoader(ClassLoader cl)方法, 获取和设置当前线程的类加载器).
如果类A中引用了类B, JVM将使用加载A的加载器来加载B.
还可以直接调用ClassLoader.loadClass(...)方法来指定某个类加载器去加载某个类.


23. 自定义类加载器:
自己写的的类加载器, 必须继承java.lang.ClassLoader抽象类.
主要涉及到findClass和defineClass方法.
例子: [java]
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
i