JAVA基础8(代码剖析)

类加载全过程
 1.new 一个类对象
 2.调用类的静态成员(除了final常量)和静态方法
 3.使用java.lang.reflect包的方法对类进行发射调用
 4.当虚拟机启动,java hello 则一定会初始化hello类 说白了就是先启动main方法所在的类
 5.当初始化一个类,如果其父类木有被初始化 则先会初始化他的父类
 
类的被动引用(不会发生类的初始化)
1.当访问一个静态域时, 只有真正声明这个域的类才会被初始化
  通过子类引用父类的静态变量 不会导致子类初始化
2.通过数据定义类引用 不会触发此类的初始化
3.引用常量不会触发此类的初始化(常量在编译阶段就存了调用类的常量池中了)









被不同加载器加载的同一个类 被视为不同的类

案例 自定义类加载器

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 自定义文件系统类加载器
 * @author 尚学堂高淇 www.sxt.cn
 *
 */
public class FileSystemClassLoader extends ClassLoader {
	
	//com.bjsxt.test.User   --> d:/myjava/  com/bjsxt/test/User.class      
	private String rootDir;
	
	public FileSystemClassLoader(String rootDir){
		this.rootDir = rootDir;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		Class<?> c = findLoadedClass(name);
		//应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。
		if(c!=null){
			return c;
		}else{
			ClassLoader parent = this.getParent();
			try {
				c = parent.loadClass(name);	   //委派给父类加载
			} catch (Exception e) {
//				e.printStackTrace();
			}
			
			if(c!=null){
				return c;
			}else{
				byte[] classData = getClassData(name);
				if(classData==null){
					throw new ClassNotFoundException();
				}else{
					c = defineClass(name, classData, 0,classData.length);
				}
			}
			
		}
		
		return c;
		
	}
	
	private byte[] getClassData(String classname){   //com.bjsxt.test.User   d:/myjava/  com/bjsxt/test/User.class
		String path = rootDir +"/"+ classname.replace('.', '/')+".class";
		
//		IOUtils,可以使用它将流中的数据转成字节数组
		InputStream is = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try{
			is  = new FileInputStream(path);
			
			byte[] buffer = new byte[1024];
			int temp=0;
			while((temp=is.read(buffer))!=-1){
				baos.write(buffer, 0, temp);
			}
			
			return baos.toByteArray();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			try {
				if(is!=null){
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(baos!=null){
					baos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}



案例:改变当前线程的加载器

/**
 * 线程上下文类加载器的测试
 * @author 尚学堂高淇 www.sxt.cn
 *
 */
public class Demo05 {
	public static void main(String[] args) throws Exception {
		ClassLoader loader = Demo05.class.getClassLoader();
		System.out.println(loader);
		
		
		ClassLoader loader2 = Thread.currentThread().getContextClassLoader();
		System.out.println(loader2);
		
		Thread.currentThread().setContextClassLoader(new FileSystemClassLoader("d:/myjava/"));
		System.out.println(Thread.currentThread().getContextClassLoader());
		
		Class<Demo01> c = (Class<Demo01>) Thread.currentThread().getContextClassLoader().loadClass("com.bjsxt.test.Demo01");
		System.out.println(c);
		System.out.println(c.getClassLoader());
		
	}
}


1.内部类仍然是一个独立的类 ,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号
2.内部类可以使用修饰符(public ,protected, default,private)
静态内部类的基本用法:
 a.静态内部类可以包含静态成员, 非静态成员
 b.静态内部类可以直接调用外部类的静态属性,静态方法,但不能调用外部类的普通属性 普通方法
 c.在不相关的类中,可以直接创建静态内部类的对象(不需要通过所在外部类)
 d.静态内部类实际上和外部类联系很少,也就是命名空间上的联系
 
成员内部类(普通内部类)
成员内部类基本用法:
  a.成员内部类就像一个成员变量一样存在于外部类中
  b.成员内部类可以访问外部类的所有成员(包含:private)
  c.成员内部类的this指内部类对象本身,要拿到外部类对象可以使用:外部类名+.this
     成员内部类的对象是一定要绑到一个外部类的对象上的,因此:创建成员内部类对象时需要持有外部类对象的引用。
     因此, 要先有外部类对象, 后有成员内部类对象 
  d.成员内部类不能有静态成员
  e.成员内部类对象的创建方式:
    外部类内部  Inner inner= new Inner()
    外部类外部   Inner inner= new Outer().Inner();

方法类基本用法:
  a.方法内部类的地位和方法的局部变量的位置类似
     因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如 public, private, protected,static transient等
  b.方法内部类只能在声明的方法内是可见的
     因此定义局部内部类之后,想用的话就要在此方法内直接实例化,记住这里顺序不能反了,一定要先声明后时候,否则编译器会说找不到
  c.方法内部类不能访问定义它的方法内的局部变量, 除非这个变量被定义为final
     本质原因;局部变量和方法内部类生命周期不一致
 d.方法内部类只能包含非静态成员
 
 
匿名内部类:
   1.匿名内部类的实例化方法:new SomeInterfaceOrClass(){}
      意思是创造一个实现(继承)了 SomeInterfaceOrClss的类对象
   2.根据声明的位置, 判断匿名内部类是成员内部类还是方法内部类
      注: 一般是 方法内部类 具备方法内部类的特征
三种使用方法;  a.继承式  b接口式   c.参数式


 案例:内部类

public class Demo02{
  public static void main(String[] args){
   Outer02.StaticNestedClass osic= new Outer02.StaticNestedClass();  //在不相关的类中,可以直接创建静态内部类的对象(不需要通过所在外部类)
   // 或者  这种方式要import  xxx.xxx.Outer02.StaticNestedClass;
    StaticNestedClass osic= new StaticNestedClass();
  }

}

class Outer02{
   int c =5;
   static int d=5;
   
   void ttt(){
     StaticNestedClass sic= new StaticNestedClass();
   }

   //静态内部类
   static class StaticNestedClass{
      int a=0;             //静态内部类可以包含静态成员, 非静态成员
	  static int b=0;      //静态内部类可以包含静态成员, 非静态成员
	  public void test(){
	    System.out.println(d); //静态内部类可以直接调用外部类的静态属性,静态方法,
		 System.out.println(c); //但不能调用外部类的普通属性 普通方法
	  }
	  
   }
   //普通内部类(成员内部类)
   private class FieldInnerClass{
    static int e=0;   //成员内部类不能有静态成员
   }
   void syaHello()
   {
      //方法内部类(局部内部类)
      class LocalClass{
	  }
   }
   //匿名内部类
   Runable runable =new Runable(){ //两个作用,定义了匿名内部类的类体,船舰了匿名内部类的一个实例
   @Overide
   public void run() {
   }
   };

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值