Java内部类两个问题

最近回顾了下内部类的用法,有两个问题备忘下。

1 内部类标准用法

java中内部类用处很广,但是感觉标准用法如下:

内部类child使用private修饰符,实现一个公开的接口interface,然后通过父类parent的public方法初始化newInstance,在外部通过接口interface访问,而内部类child又可以访问父类parent的内部资源

其中最经典的例子当属于util中的Iterator方式了。父类AbstractList中有private内部类Itr,实现了java.util.Iterator接口,然后内部类中可以访问AbstractList的各种变量和方法

private class Itr implements Iterator<E>{
    public E next() {
            checkForComodification();
	    try {
		E next = get(cursor);
		lastRet = cursor++;
		return next;
	    } catch (IndexOutOfBoundsException e) {
		checkForComodification();
		throw new NoSuchElementException();
	    }
	}
   final void checkForComodification() {
     if (modCount != expectedModCount)
         throw new ConcurrentModificationException();
   }
}

 在外部通过接口访问

       List list=new ArrayList();
          Iterator it=list.iterator();//通过接口访问
       it.next();

 这样做能够实现外部接口,访问内部变量,且不暴露访问细节

 因为内部类是private的,只能在父类内部访问,在外部不能访问,因此就和根本不存在一样

 

          List list=new ArrayList();
          List.Itr it=list.new Itr();//不能通过这种标准方式访问

 

2 匿名内部类和final 

另外关于匿名内部类只能访问final类型的局部变量的原因,确定的是匿名内部类一般可能是线程之类的,生命周期远比一般的方法调用要长。

有一种说法是内部类里面将该变量copy一份,如果该变量还可以随意赋值的话,可能导致内部类中的那份copy和外部的相比不一样了,因此需要final修饰符,但是感觉这样不对,写了个例子测试了下,如下:

private static void test() throws Exception{
	final List<String> list = new ArrayList<String>();
	list.add("aa");
	list.add("bb");
	new Thread() {
		public void run() {
			int i = 0;
			while (true) {
				i++;
			                if (i == 10)
				     break;
				System.out.println(list);
		                                try {		Thread.sleep(1000);
		                                     } catch (InterruptedException e) {
		                                           e.printStackTrace();
			                           }
			                   }
			          }
		      }.start();
	list.add("cc");
	Thread.sleep(2000);
	list.add("dd");
	}

   代码的目的是匿名类里面不停访问list,匿名类外部修改list,结果如下:

[aa, bb, cc]
[aa, bb, cc]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]

   从结果可以看到匿名类内部和外部访问的是同一个对象,而不是通过copy的方式。

   因此怀疑final类型的局部变量的生命周期比一般的局部变量周期要长,在方法调用完毕之后还存在。

你可能感兴趣的:(java,thread)