Java匿名内部类访问全局变量和局部变量的注意事项

java 复制代码
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;

import javax.swing.*;
public class DemoAA extends JFrame{
	PanelAA panel;
	DemoAA(){
		super("练习监听");
		setBounds(600, 200, 600, 600);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		panel = new PanelAA();
		add(panel);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(() ->{
			new DemoAA().setVisible(true);
		});
	}

	private class PanelAA extends JPanel{
		JLabel l1,l2;
		int x=0,y=0;
		PanelAA(){
			setLayout(new GridLayout(2, 1,0,10));
	        l1 = new JLabel("左上角文字", SwingConstants.LEFT); // 水平左对齐
	        l1.setVerticalAlignment(SwingConstants.TOP); // 垂直顶部对齐
			l1.setFont(new Font("黑体", Font.BOLD, 20));	
			add(l1);
			//鼠标监听
			addMouseMotionListener(new MouseMotionListener() {
				
				@Override
				public void mouseMoved(MouseEvent e) {
					// TODO Auto-generated method stub
					x =e.getX();
					y=e.getY();
					repaint();
				}
				
				@Override
				public void mouseDragged(MouseEvent e) {
					// TODO Auto-generated method stub
					
				}
			});
		}
		
		@Override
		protected void paintComponent(Graphics g) {
			// TODO Auto-generated method stub
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D)g;
			g2.setFont(new Font("黑体", Font.BOLD, 24));
			g2.setColor(Color.RED);
			g2.drawString("坐标 X:"+x+" Y:"+y, 10, 60);
		}

	}
}		

为什么匿名内部类能访问外部变量

背后的原理(简单版)

Java 为了让匿名内部类能访问外部变量,实际上在背后偷偷做了这些事:

  1. 自动传递 :Java 编译器会把外部类的 this 引用(指向 PanelAA 实例)传递给匿名内部类
  2. 隐形桥梁 :匿名内部类通过这个 this 引用,就能找到外部的 xy

如果是局部变量呢?

有趣的是,如果 xy 是方法内的局部变量(不是类的成员变量),规则就不同了:

java 复制代码
void someMethod() {
    int localX = 0; // 局部变量
    addMouseMotionListener(new MouseMotionListener() {
        public void mouseMoved(MouseEvent e) {
            localX = e.getX(); // 这会报错!不能修改局部变量
        }
    });
}

这时候 Java 会说:

🚨 "嘿!局部变量 localX 必须声明为 final 或等效于 final 才能被匿名内部类访问!"

为什么有这个区别?

  • 成员变量:属于对象,生命周期和对象一样长,安全可访问
  • 局部变量方法执行完就可能消失匿名内部类可能活得比它久,所以 Java 要限制
相关推荐
wno7043 分钟前
Spring Security基础使用
java·后端·spring
孙启超14 分钟前
【AI开发之Rust】第 8 课:泛型、trait 与 trait 对象
开发语言·后端·rust
2501_9336707940 分钟前
经营财务岗技能栈拆解:Excel、SQL、BI、预算分析怎么准备
开发语言
小蒜学长41 分钟前
基于RFID技术的仓储管理系统设计(代码+数据库+LW)
java·数据库·spring boot·后端·rfid技术·仓储管理
梦影_1 小时前
Langchain简单快速上手教程(五)——聊天模型之流式传输
java·数据库·人工智能·python·langchain
数据狐(Datafox)1 小时前
1688商品列表API接口解析(附 JSON 样例)
java·开发语言·数据库·爬虫·json
xcl09251 小时前
健身场馆无人自动化系统:从架构设计到落地实践
java·spring boot
EatFan1 小时前
一个二维码背后的系统设计:批次生成、绑定、扫码与数据统计怎么做?
java·后端·微信小程序·二维码·qrcode
白远山1 小时前
自助健身小程序源码:架构拆解、核心链路与本地部署实战
java·架构·uni-app·需求分析
小灰灰搞电子2 小时前
Rust Once 、OnceLock、LazyLock 一次性初始化详解
开发语言·后端·rust