JAVA基础8(代码剖析)
2015-08-25 10:36
561 查看
类加载全过程
1.new 一个类对象
2.调用类的静态成员(除了final常量)和静态方法
3.使用java.lang.reflect包的方法对类进行发射调用
4.当虚拟机启动,java hello 则一定会初始化hello类 说白了就是先启动main方法所在的类
5.当初始化一个类,如果其父类木有被初始化 则先会初始化他的父类
类的被动引用(不会发生类的初始化)
1.当访问一个静态域时, 只有真正声明这个域的类才会被初始化
通过子类引用父类的静态变量 不会导致子类初始化
2.通过数据定义类引用 不会触发此类的初始化
3.引用常量不会触发此类的初始化(常量在编译阶段就存了调用类的常量池中了)
![](http://img.blog.csdn.net/20150824232517945)
![](http://img.blog.csdn.net/20150824232528684)
![](http://img.blog.csdn.net/20150824232535768)
![](http://img.blog.csdn.net/20150824232545385)
被不同加载器加载的同一个类 被视为不同的类
![](http://img.blog.csdn.net/20150825002114916)
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.参数式
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() { } }; }
相关文章推荐
- java中日期工具类
- 《Java实战开发经典》第五章5.3
- Java IO流->节点流->字节流:FileInputStream与FileOutputStream
- Eclipse快捷键大全
- Java总结
- SpringMVC单元测试
- eclipse 插件安装
- java内存分配分析/栈内存、堆内存
- 【JAVA】WEB开发实际任务——记录
- 深入理解Java的接口和抽象类
- Java程序性能优化
- 学习笔记:JAVA RMI远程方法调用简单实例
- java.lang.NoClassDefFoundError:的处理
- volatile关键字
- 《Java实战开发经典》第五章5.2
- java发送邮件
- Java @注解
- 【Java EE 学习 30】【闪回】【导入导出】【管理用户安全】【分布式数据库】【数据字典】【方案】
- eclipse导入注释模板
- Java二分查找算法