版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/y41992910/article/details/89705269
最近用上了静态内部类,作为建造者模式.
自然就会有个疑问.静态内部类,会不会有线程安全的问题?因为静态的,那么这个静态内部类是所有的外部类实例共用一个呢(这样会有线程安全的问题),
还是每个实例有自己对应的静态内部类实例?(这样不会有线程安全的问题)
根据测试结果,静态内部成员类,没有出现线程安全的问题.
com.itrus.portal.common.test.DuoShuXingGouZhaoQiCeShi
Builder@3e4a0b0a
因为虽然静态内部类是静态的,但是调用DuoShuXingGouZhaoQiCeShi.Builder builder = new DuoShuXingGouZhaoQiCeShi.Builder(page, size);
的时候,都会新生成一个builder对象,只是用了静态的方式来标识他不属于某个对象,而是属于类.
就类似于我们在类A中定义puiblic static String s1;
就类似于我们在类B中定义puiblic static String s2;
s1和s2自然是两个实例.
package com.itrus.portal.common.test;
public class Main {
/**
* 开始ThreadTest
开始ThreadTest2
DuoShuXingGouZhaoQiCeShi [page=2, size=2, fat=2]
结束ThreadTest2
DuoShuXingGouZhaoQiCeShi [page=1, size=1, fat=1]
结束ThreadTest
com.itrus.portal.common.test.DuoShuXingGouZhaoQiCeShi$Builder@65eb1b78
com.itrus.portal.common.test.DuoShuXingGouZhaoQiCeShi$Builder@3e4a0b0a
根据测试结果,静态内部成员类,没有出现线程安全的问题.
因为虽然静态内部类是静态的,但是调用DuoShuXingGouZhaoQiCeShi.Builder builder = new DuoShuXingGouZhaoQiCeShi.Builder(page, size);
的时候,都会新生成一个builder对象,只是用了静态的方式来标识他不属于某个对象,而是属于类.
就行平常我们定义了一个静态成员一样,难道这个静态成员全局就只有一个实例吗,当然不是,在其他类或者地方也会有这个类对应的实例.
所以静态内部类和平常的内部类唯一的几点不同就是
3.静态内部类有特殊的地方吗?
从前面可以知道,静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的,这个读者可以自己尝试反编译class文件看一下就知道了,是没有Outter this&0引用的。
4.静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
而静态内部类不用产生外部类的实例化对象即可产生内部类的实例化对象
* @param args
*/
public static void main(String[] args) {
ThreadTest test = new ThreadTest(1, 1, 1);
ThreadTest2 test2= new ThreadTest2(2, 2, 2);
test.start();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
test2.start();
}
}
测试类
package com.itrus.portal.common.test;
public class DuoShuXingGouZhaoQiCeShi {
private final int page;
private final int size;
private final int fat;
/**
* 测试静态内部类的线程安全问题
* @author he_guanhong
*
*/
public static class Builder{
//必须输入的值
private final int page;
private final int size;
//其他可选的值,默认
private int fat = 0;
public Builder(int page,int size){
this.page = page;
this.size = size;
}
public Builder fat(int fat){
this.fat = fat;
return this;
}
public DuoShuXingGouZhaoQiCeShi build(){
return new DuoShuXingGouZhaoQiCeShi(this);
}
}
private DuoShuXingGouZhaoQiCeShi(Builder builder){
this.page = builder.page;
this.size = builder.size;
this.fat = builder.fat;
}
@Override
public String toString() {
return "DuoShuXingGouZhaoQiCeShi [page=" + page + ", size=" + size
+ ", fat=" + fat + "]";
}
}
package com.itrus.portal.common.test;
public class ThreadTest extends Thread{
private int page;
private int size;
private int fat;
public ThreadTest(int page, int size, int fat) {
super();
this.page = page;
this.size = size;
this.fat = fat;
}
public void run(){
System.out.println("开始ThreadTest");
DuoShuXingGouZhaoQiCeShi.Builder builder = new DuoShuXingGouZhaoQiCeShi.Builder(page, size);
try {
sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DuoShuXingGouZhaoQiCeShi duoShuXingGouZhaoQiCeShi =builder.fat(fat).build();
System.out.println(duoShuXingGouZhaoQiCeShi);
System.out.println("结束ThreadTest");
};
}
package com.itrus.portal.common.test;
public class ThreadTest2 extends Thread{
private int page;
private int size;
private int fat;
public ThreadTest2(int page, int size, int fat) {
super();
this.page = page;
this.size = size;
this.fat = fat;
}
public void run() {
System.out.println("开始ThreadTest2");
DuoShuXingGouZhaoQiCeShi.Builder builder = new DuoShuXingGouZhaoQiCeShi.Builder(page, size);
DuoShuXingGouZhaoQiCeShi duoShuXingGouZhaoQiCeShi =builder.fat(fat).build();
System.out.println(duoShuXingGouZhaoQiCeShi);
System.out.println("结束ThreadTest2");
};
}