javaEE-类绑定与类加载

1、类绑定– 两种绑定方式

       静态绑定 - 编译级别已经绑定

       动态绑定 – 运行时才会绑定

public class BoundDemo {
	public static void main(String[] args) {
		A a = new B();
		System.err.println(a.age);//100
		System.err.println(a.num);//100
		a.abc();//abc...1000 所有非静态分开方法都是在运行时绑定,动态绑定,其他的都是静态绑定
				//静态绑定是指在编译时已经指定引用的就是静态绑定
		a.aaa();//aaa..100
	}
}
class A{
	public int age=100;
	public static int num = 100;
	public void abc(){
		System.err.println("abc....100");
	}
	public static void aaa(){
		System.err.println("aaa....100");
	}
}
class B extends A{
	public int age=1000;
	public static int num = 1000;
	public void abc(){
		System.err.println("abc....1000");
	}
	public static void aaa(){
		System.err.println("aaa....1000");
	}
}

3、 类加载

所有类加载器,都是ClassLoader的子类。

类加载器永远以.class运行的目录为准。

 

 

读取classpath根目录下的文件有以下几种方式:

在Java项目中可以通过以下方式获取classspath下的文件:


	public void abc(){
		//每一种读取方法,使用某个类获取Appclassloader
		ClassLoader cl = ReadFile.class.getClassLoader();
		URL url = cl.getResource("a.txt");
		System.err.println("url1 is:"+url.getPath());
		
		//第二种方式,直接使用ClassLoader
		URL url2 = ClassLoader.getSystemResource("a.txt");
		System.err.println("url2 is:"+url2.getPath());
	}


/**
	 * 一个类的加载分两种情况
	 * 
	 * 第一种是java项目
	 * 		在java项目中由于没有容器,只有JVM,所以只有三个类加载器(...)
	 * 		所以在java项目中所有用户类都是被AppClassLoader(用java写的)加载的。
	 * 		而所有如String这样的系统类,都是被BootStrap(用C语言写)加载的。
	 * 
	 * 第二种是web项目	
	 * 		如果一个类运行在容器如tomat中,由于tomcat已经扩展了类加载器
	 * 		WebAppClassLoader,StandardClassLoader
	 * 		所以所有的运行在tomcat中的类都是被Stan..加载的。
	 * 		
	 * 		所有的系统类如java.lang.String,ClassLoader不管是运行在java项目中
	 * 		还是运行在tomcat中都永远是被BootStrap加载的。
	 * 
	 */

在Tomcat中tomcat又声明了两个类载器:

       StandardClassLoader–加载tomcat/lib/*.jar  - serlvetapi.jar

              Webappclassloader/加载 tomcat/webapps/project/web-inf/lib/*.jar  && web-inf/classes/*.class

 

在任何的项目中,获取类的加载器都应该使用以下方式:

       SomeClass(你写的).class.getClassLoader().getResource;获取到这个类的类加载器

              在java项目中是:AppClassLoader

              在Web项目中:WebAppClassLoader



测试父类加载器:
public class OneServlet extends HttpServlet {
	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		ClassLoader loader = OneServlet.class.getClassLoader();//WebAppClassLoader
		int index=1;
		while(loader!=null){
			System.err.println((index++)+"类加载器是:"+loader.getClass());					 loader=loader.getParent();//获取父类加载器
		}
	}
}

运行的结果:

1类加载器是:classorg.apache.catalina.loader.WebappClassLoader

2类加载器是:classorg.apache.catalina.loader.StandardClassLoader

3类加载器是:class sun.misc.Launcher$AppClassLoader

4类加载器是:class sun.misc.Launcher$ExtClassLoader

4、 自定义类加载器

 

JDK以哪一个类加载器读取A类的字节码,则A类就是被哪一个类加载器加载 的。

    一个同名的类,是否可以相互转换,要看是否是在同个类加载器中

public class MyClassLoader2 extends ClassLoader {
	/**
	 * name:cn.itcast.demo.Person
	 * 根据包名找到.class文件
	 * cn.itcast.demo.person = > cn/itcast/demo/Person.class
	 */
	public Class<?> findClass(String name) throws ClassNotFoundException {
		String classNameWithPackage=name;
		Class<?> cls = null;
		try {
			//先将
			name = name.replace(".","/");
			name +=".class";
			//确定目录
			URL url = MyClassLoader2.class.getClassLoader().getResource(name);
			System.err.println(">>:"+url.getPath());
			File file = new File(url.getPath());
			InputStream in = new FileInputStream(file);
			//读取这个.class文件的字节码
			byte[] b = new byte[in.available()];//直接声明这个字节大小为这个文件的大小
			int len = in.read(b);//len=621
			System.err.println(len);
			/**
			 * 第一个参数是类名
			 */
			cls = defineClass(classNameWithPackage,b,0,len);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cls;
	}
}

测试类自定义类加载器“

public class ClassLoaderDemo {
	public static void main(String[] args) throws Exception {
		MyClassLoader2 mc = new MyClassLoader2();
		Class cls = mc.findClass("cn.itcast.demo.Person");
		Object o = cls.newInstance();
		System.err.println("toString:"+o+","+o.getClass().getClassLoader());
		//直接使用peron是 AppClassLoader
		System.err.println(">>:"+Person.class.getClassLoader());
		//由于o是由mc加载的。而Person是由App加载的,所有不可以转换=来自于两个不同的加载器
		//Person p = (Person) o;//类型转换错误ClassCastException
		//System.err.println(p);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值