您的位置:首页 > 编程语言 > Java开发

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.引用常量不会触发此类的初始化(常量在编译阶段就存了调用类的常量池中了)









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

案例 自定义类加载器

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() {
}
};

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: