天天看點

JDK1.8之後匿名内部類通路方法中的局部變量不用加final修飾

JDK1.8之後匿名内部類通路方法中的局部變量不用加final修飾

今天在學習ThreadLocal類,在一個方法中寫了一個匿名内部類,然後使用方法中的局部變量,發現不用加final修飾變量

但是如果修改了變量值,在ide中會報紅顯示,局部變量必須是有效的final類型

附上代碼,可以學習一下ThreadLocal

package com.edou.test;

import org.junit.Test;

/**
 * @ClassName TestInnerClass
 * @Description 測試匿名内部類通路局部變量是否加final
 * @Author 中森明菜
 * @Date 2020/9/27 8:46
 * @Version 1.0
 */
public class TestInnerClass {
    @Test
    public void testRef() {
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        threadLocal.set("test1");
        Runnable r1 = () -> {
            threadLocal.set("test2");
            String result = threadLocal.get();
            // test2
            System.out.println(result);
        };
        r1.run();
        Runnable r2 = () -> {
            threadLocal.set("test3");
            String result = threadLocal.get();
            // test3
            System.out.println(result);
        };
        r2.run();
    }
    @Test
    public void testBasicValue() {
        int a = 1;
        Runnable r = () -> {
            // a = 2
            System.out.println(a);
        };
        r.run();
    }
}

           

在testRef中,局部變量是引用類型,我們改變的是它内部的變量值,并沒有改變它自身的引用位址,但是如果我們在lamda中給局部變量設定 新的引用位址,也就是改變它的指針指向,也會報錯。

在testBasicValue中,我們的局部變量是基本數值類型,如果在lamda中通路不加final沒問題,但是如果修改變量值,也會爆紅。

上面是用lamda表達式實作的,下面是用匿名内部類實作的案例。

package cn.edou.thread;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

public class Demo1 {
	@Test
	public void fun1(){
		ThreadLocal<String> tl = new ThreadLocal<String>();
		tl.set("hello");
		System.out.println(Thread.currentThread().getName());
		new Thread(){
			public void run() {
				tl.set("world");
				System.out.println(Thread.currentThread().getName());
				System.out.println(tl.get());
			}
		}.start();
		System.out.println(tl.get());
	}
	@Test
	public void fun2(){
		Map<Thread,String> map = new HashMap<Thread, String>();
		map.put(Thread.currentThread(), "hello");
		new Thread(){
			public void run() {
				System.out.println(map.get(Thread.currentThread()));
			}
		}.start();
		System.out.println(map.get(Thread.currentThread()));
	}
}
/*
 * ThreadLocal内部結構是Map
 */
class TL<T> {
	private Map<Thread,T> map = new HashMap<Thread,T>();
	public void set(T data){
		map.put(Thread.currentThread(), data);
	}
	public T get(){
		return map.get(Thread.currentThread());
	}
	public void remove(){
		map.remove(Thread.currentThread());
	}
}