首页 > 编程语言 >java匿名内部类访问局部变量为啥要用final

java匿名内部类访问局部变量为啥要用final

时间:2022-11-15 22:12:20浏览次数:48  
标签:java Demo 局部变量 public User new setAge final user

要明白这个问题,首先要知道java参数传递方式只有值传递,即函数调用过程中形参的改变不会影响实参。允许一下代码:

 1 public class Demo {
 2 
 3     private User user;
 4     public Demo(User user){
 5         user.setName("李四");
 6         user.setAge(234);
 7         this.user=user;
 8     }
 9 
10     public static void main(String[] args) {
11         User user=new User();
12         user.setName("张三");
13         user.setAge(20);
14         Demo demo=new Demo(user);
15         System.out.print(user);
16     }
17 
18 

 

 

 

 

 

 

 哎?怎么和书上说的对不上?说好的值传递呢?这个问题也困扰了我一段时间。再修改一下运行:

 1 public class Demo {
 2 
 3     private User user;
 4     public Demo(User user){
 5         user=new User();
 6         user.setName("李四");
 7         user.setAge(234);
 8         this.user=user;
 9     }
10 
11     public static void main(String[] args) {
12         User user=new User();
13         user.setName("张三");
14         user.setAge(20);
15         Demo demo=new Demo(user);
16         System.out.print(user);
17     }
18 
19 }

 

 

 这一次我在第7行加了一行代码 user=new User(); 重新创建了对象,执行结果就完全不一样了。为啥会出现这种情况?这是因为java引用对象的传递是将实际参数的引用地址复制一份传给形参,即两个引用地址对应一个对象,当形参修改时实参也会跟着变化,即第一种情形。若形参重新创建一个对象,会重新分配一个新对象的引用地址,这样形参的修改不会影响实参,即第二情形

ps:若参数是基本类型,那么传递的是复制基本类型的值,形参的改变不会影响实参。

了解的参数传递,我们来看下包含匿名内部类使用代码:

public class Demo {

    private User user;
    public Demo(User user){
        user=new User();
        user.setName("李四");
        user.setAge(234);
        this.user=user;
    }

    public static void main(String[] args) {
        final User user=new User();
        user.setName("张三");
        user.setAge(20);
        //Demo demo=new Demo(user);
        //System.out.print(user);

        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(user);
            }
        });
        thread.start();
    }

}

在看下匿名内部类Demo$1.class 反编译后结果

class Demo$1 implements Runnable {
    Demo$1(User var1) {
        this.val$user = var1;
    }

    public void run() {
        System.out.println(this.val$user);
    }
}

编译器将匿名内部类所使用的局部变量传入了构造函数中,根据我们对前面参数传递的理解,这是一个复制的引用地址。但是从程序员的角度来看,这两个应该是一个对象。如果java不在语义上限制,有可能会造成我们人认为是一个对象,而机器理解是两个对象,造成程序得出结果和预期不符的情况,所以java在匿名类中引用局部变量必须用final来限制修改,避免造成歧义。

标签:java,Demo,局部变量,public,User,new,setAge,final,user
From: https://www.cnblogs.com/xc9497/p/16894185.html

相关文章

  • java——API——Scanner类
    Scanner概述一个可以解析基本类型和字符串的简单文本扫描器。Scanner类的功能:可以实现键盘输入数据,到程序当中。属于引用类型引用类型的一般使用步骤1.导包使用import......
  • Java三大版本&JDK、JRE、JVM
    Java三大版本&JDK、JRE、JVMJava三大版本WriteOnce、RunAnywhere(一次编写,随处运行)JavaSE:标准版(桌面程序、控制台开发......),Java的基础与核心,也是JavaEE和JavaME......
  • Java基础语法01
    注释注释不会被执行,属于解释代码的内容单行注释以//开头,只能注释一行文字多行注释以/开头,以/结尾,可以注释多行文字文档注释以/**开头,以*/结尾标识符Ja......
  • 后端程序员必会的前端知识-02:JavaScript
    第二章.Javascript它是一种脚本语言,可以用来更改页面内容,控制多媒体,制作图像、动画等等例子修改页面内容js代码位置<script> //js代码</script>引入js脚......
  • JavaScript基础知识
    变量变量是数据的命名存储,我们可以用变量来保存商品、访客和其他信息。在JavaScript中创建一个变量,需要用到关键字let。例如:letmessage="hello";//将字符串hello保......
  • java类与对象
    1.不是static类型则需要定义一个对象变量,然后“创建(new)”一个对象,赋值给对象变量,现在就可以通过对象变量使用对象,主要方式有:(1)直接调用类的方法;(2)存取类的字段。2.在定义变......
  • 函数_Java
    函数基础一个典型的函数定义包括以下部分:修饰符、返回类型、函数名字、由0个或多个形参组成的列表以及函数体。如以下函数:publicclassMain{privatestaticint......
  • 复习java基础的第二天
    java流程控制1Scanner对象基本语法Scannerscanner=newScanner(System.in);next();一定要读取到有效字符后才可以结束输入。对输入有效字符之前遇到的空......
  • JAVA中字符串的插入
    一、问题描述就是我们现在有一个字符串,我们需要实现一个功能,就是选择在字符串中字符的ASCII码最大的地方,插入字符串。二、解决思路我们直接循环,获取字符串中所有的字符,......
  • java 获取字符串长度
    获取字符串长度/***获取字符串的长度,如果有中文,则每个中文字符计为2位*@paramvalue指定的字符串*@return字符串的长度*/publicstaticintlength......