Cannot refer to a non-final variable file inside an inner class defined in a different method

java多线程学习:
生产者和消费者

问题:
Cannot refer to a non-final variable file inside an inner class defined in a different method
如果定义一个局部内部类,并且局部内部类使用了一个在其外部定义的对象,为什么编译器会要求其参数引用是final呢?
注意:局部内部类,包括匿名内部类。

自己写的生产和消费者的类遇到的问题, final Goods pru = new Goods();
没有在Goods 前加final,里面 pru.produce(str) ;
始终报错Cannot refer to a non-final variable file inside an inner class defined in a different method
Thread thread1 = new Thread(new Runnable(){
public void run(){
while(pru.num<=20){
pru.produce(str) ;

}
}

package test;

public class PruConsumer {

/**
* @param args生产者和消费者的游戏
* @author zhuyh
*/
public static void main(String[] args) {
class Goods{
private int num;
private String name;
private boolean flags =false;

public synchronized void produce( String name){
while(flags){
try{

wait();

}catch(InterruptedException e){
e.printStackTrace();

}
}
this.name = name+"--编号" + num++;
System.out.println(Thread.currentThread().toString() +" 生产了:" +this.name);
flags= true;
notifyAll();

}

public synchronized void consumer(){
while(!flags){
try{

wait();

}catch(InterruptedException e){
e.printStackTrace();

}
}
System.out.println(Thread.currentThread().toString() +" :消费了:" +this.name);
flags= false;
notifyAll();

}

}

// TODO Auto-generated method stub
final Goods pru = new Goods();
final String str="商品";
Thread thread1 = new Thread(new Runnable(){
public void run(){
while(pru.num<=20){
pru.produce(str) ;

}
}

},"生产者一号");
thread1.start();

Thread thread2 = new Thread(new Runnable(){
public void run(){
while(pru.num<=20){
pru.produce(str) ;

}
}
},"生产者二号");
thread2.start();

Thread thread3 = new Thread(new Runnable(){
public void run(){
while(pru.num<=20){
pru.consumer();

}
}
},"消费者一号");
thread3.start();

Thread thread4 = new Thread(new Runnable(){
public void run(){
while(pru.num<=20){
pru.consumer();

}
}
},"消费者二号");
thread4.start();

}

}

网上找到解释
JVM中每个进程都会有多个根,每个static变量,方法参数,局部变量,当然这都是指引用类型.基础类型是不能作为根的,根其实就是一个存储地址.垃圾回收器在工作时先从根开始遍历它引用的对象并标记它们,如此递归到最末梢,所有根都遍历后,没有被标记到的对象说明没有被引用,那么就是可以被回收的对象(有些对象有finalized方法,虽然没有引用,但JVM中有一个专门的队列引用它们直到finalized方法被执行后才从该队列中移除成为真正没有引用的对象,可以回收,这个与本主题讨论的无关,包括代的划分等以后再说明).这看起来很好但是在内部类的回调方法中,s既不可能是静态变量,也不是方法中的临时变量,也不是方法参数,它不可能作为根,在内部类中也没有变量引用它,它的根在内部类外部的那个方法中,如果这时外面变量s重指向其它对象,则回调方法中的这个对象s就失去了引用,可能被回收,而由于内部类回调方法大多数在其它线程中执行,可能还要在回收后还会继续访问它.这将是什么结果?而使用final修饰符不仅会保持对象的引用不会改变,而且编译器还会持续维护这个对象在回调方法中的生命周期.所以这才是final变量和final参数的根本意义.

时间: 2024-11-08 21:25:12

Cannot refer to a non-final variable file inside an inner class defined in a different method的相关文章

VS2010编译错: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0403...的解决方法

最近拿到一个别人的工程,是使用VS.net创建的,而我的机器上只有vs2010,于是用自带的转换工具将它转换成vs2010的工程,转换之前我就很担心,怕转换完后会出问题,但是没有办法,我实在是不想再安一个vs.net了. 转完后果不其然真出了问题,在重新build工程时,报了一大堆错误,其中第一个就是“fatal error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0403. Val

fatal error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0500. Val

fatal error C1189: #error :  This file requires _WIN32_WINNT to be#defined at least to 0x0500. Value 0x0501 or higher is recommended. VS2003的工程转换成VS2010后编译报错. 定位到afxcomctl32.h文件,这是系统文件没有做任何更改,主要还是版本兼容性问题. 修改方法: 新建一个targetver.h头文件,复制以下代码: #pragma once

This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended

VS2005转换成VS2010时出现的问题: 解决方法:打开stdafx.h文件修改如下: 注释掉: //#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.//#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or lat

Java8增加功能--Effectively final 功能

java8新增了很多功能,可以大大简化代码,这个系列将会一一辅助代码加以介绍. 局部内部类和匿名内部类访问的局部变量必须由final修饰,java8开始,可以不加final修饰符,由系统默认添加.java将这个功能称为:Effectively final 功能. 下面是完整掩饰代码(至少使用jdk1.8版本): public class EffectivelyFinalDemo { public static void main(String[] args) { //局部内部类和匿名内部类访问的

【转】Java 内部类种类及使用解析

Java 内部类种类及使用解析 内部类Inner Class 将相关的类组织在一起,从而降低了命名空间的混乱. 一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分. Java中的内部类共分为四种: 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类local inner class 匿名内部类anonymous inner class 静态内部类Static

为什么说Java匿名内部类是残缺的闭包

前言 我们先来看一道很简单的小题: public class AnonymousDemo1 { public static void main(String args[]) { new AnonymousDemo1().play(); } private void play() { Dog dog = new Dog(); Runnable runnable = new Runnable() { public void run() { while(dog.getAge()<100) { // 过

java学习笔记9--内部类总结

java学习笔记系列: java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Object类 java学习笔记5--类的方法 java学习笔记4--对象的初始化与回收 java学习笔记3--类与对象的基础 java学习笔记2--数据类型.数组 java学习笔记1--开发环境平台总结 本文地址:http://www.cnblogs.com/archimedes/p/java-study-note9.html,转载请注明源地址. java内部类分为:

Java编程思想(七) —— 内部类

刚刚看到论坛推荐,阿里的校招没想到8月底就开始了,等春招再去试试,现在还是太嫩了点. 将一个类的定义放到另一个类定义的内部--内部类.用java写Android的朋友经常用的Listener的东西,里面就是内部类.而且,不要单纯地以为就java才能开发Android. 1)简单的内部类 内部类的功能看似隐藏了代码,其实不然. public class Ticket { class Destination{ private String content; Destination(String s)

java基础之 内部类

Java中的内部类共分为四种: 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类local inner class 匿名内部类anonymous inner class 静态内部类Static Inner Class 最简单的内部类形式. 类定义时加上static关键字. 不能和外部类有相同的名字. 被编译成一个完全独立的.class文件,名称为OuterClass$InnerClas