标题有点长,可能有点语病,先别管那么多!
首先看下面的这段代码:
public class LocalInnerClassTest{
public static void main(String[] args){
Outer obj=new Outer(); //生成一个外部类对象
SuperInner si=obj.outer(); //调用外部类中的outer()方法,返回一个SuperInner类型对象赋值给si
si.m1(); //调用被覆盖的方法m1(),输出:Inner's m1() 20
}
}
/**
*定义一个接口SuperInner,内部定义一个抽象方法m1(),无返回类型
*/
interface SuperInner{
public void m1();
}
/**
*定义一个类Outer,内部只定义一个方法outer(),返回类型为SuperInner
*/
class Outer{
public SuperInner outer(){
int a=10; //方法中定义一个局部变量a,并赋值为10
final int b=20; //再定义一个final局部变量b,初始化为20
class Inner implements SuperInner{ //在outer()方法中定义一个局部内部类Inner,实现接口SuperInner
public void m1(){ //类中只有一个覆盖接口SuperInner的方法m1()
System.out.println("Inner's m1()"+a); //编译报错
System.out.println("Inner's m1() "+b); //编译通过,输出:Inner's m1() 20
}
}
return new Inner();
}
}
我们先从主方法开始看代码的执行顺序,先生成一个Outer类对象obj,obj调用本类
中方法outer();程序开始跳到outer()方法内执行程序语句,先后生成局部变量a和b,再定义一个局部内部类Inner,返回一个
SuperInner类型的对象。将返回的SuperInner类型对象地址传给SuperInner类型对象si。si再调用m1()方法,因为已经在
局部内部类中覆盖了接口中的m1()方法,所以将调用局部内部类中的m1()方法,程序跳到局部内部类中m1()方法内执行程序语句,先输出一段字符串和
a,结果编译报错,先 将这条程序语句隐藏,执行下面的语句,你会发现编译通过而且输出Inner's m1() 20!
为
什么会这样呢?大家都知道局部变量仅仅在一个范围内有效,在方法调用完就被内存释放,在Outer类对象obj调用outer()方法时,a和b才产生,
调用结束后被内存释放,那么b这个值也就不复存在了,为什么还会输出20呢?难道局部变量被final修饰就不会被内存释放而保留?
其
实有部分操作对于程序员是透明的,那是JAVA语言开发者的小把戏,在定义a和b
时JVM(JAVA虚拟机)做了程序员看不到的操作,他将b拷贝了一份给局部内部类,也就是说JVM在局部内部类中定义了一个final int
b=20;这个操作程序员是不知道的!当调用m1()方法时输出的20并不是原来outer()方法中定义的b,而仅仅是JVM拷贝的一个副本。那么为什
么a没被打印出呢?那是因为JVM并没有拷贝它,因为没有final修饰,说明它可以被修改,如果把a 改为 a++
,此时JVM就不知道拷贝a还是a++了,所以对于无final修饰的局部变量JVM是不会拷贝传给局部内部类的,自然无法打输出!
分享到:
相关推荐
Java 中局部内部类可以访问它所在方法中定义的 final 修饰的局部变量的合理解释 在 Java 中,局部内部类可以访问它所在方法中定义的 final 修饰的局部变量,这是一个非常重要的知识点。这是因为 JVM 在编译时会将 ...
局部内部类和匿名内部类是Java中的一种特性,它们允许我们在方法内部定义类。然而,一个重要的限制是,这些内部类只能访问在其作用域内的final或者实际上等效于final的局部变量。这是因为内部类可能在外部方法结束后...
在Java编程语言中,`final`关键字有着重要的作用,它能用于修饰类、方法和变量,以限制它们的使用方式。下面将详细解释`final`修饰类、方法和变量的具体含义及其应用场景。 **final 修饰类** `final`修饰类的作用...
Java中的内部类是一种定义在另一个类内部的类,内部类提供了对包含它的外部类的直接访问。内部类主要分为四种类型:成员内部类、静态内部类、局部内部类和匿名内部类。内部类可以访问外部类的成员,包括私有成员,这...
1. **访问权限**:局部内部类可以访问方法内的局部变量,但这些变量必须声明为final。 2. **实例化**:局部内部类只能在其定义的方法或构造函数内部实例化。 3. **示例**: ```java public void method() { final...
标题中的“局部变量用final”的讨论主要聚焦于Java编程语言中的一个特性,即使用`final`关键字修饰局部变量。在Java中,`final`关键字有多种用途,包括但不限于定义不可变对象、创建常量以及限制变量的赋值次数。在...
本文将详细解释 Java 中的四种主要访问控制修饰词:`public`、`protected`、`default`(默认)、`private`,以及 `abstract` 和 `final` 的用法,并对这些修饰词的特点进行深入分析。 #### 1. 访问控制修饰词 - **...
Java编程语言中有三种主要的变量类型:成员变量(也称为实例变量)、类变量(也称为静态变量)和局部变量。理解这些变量之间的区别是掌握Java基础的重要部分,这对于编写高效、可维护的代码至关重要。 成员变量是...
- 局部内部类:定义在方法或者作用域块中,不能有访问权限修饰符,只能访问方法中被final修饰的局部变量。 - 匿名内部类:没有类名的局部内部类,通常用在需要创建一个对象时,且仅需使用一次的场合。 - 静态内部类...
- **局部内部类**:是在一个方法或构造器内部定义的类,可以访问该方法或构造器内的局部变量,但这些局部变量必须声明为`final`。 - **匿名内部类**:没有名字的内部类,通常用于实现接口或继承类时简化代码,主要...
由于局部内部类在方法内部定义,它可以访问该方法中的所有局部变量,但这要求局部变量必须被声明为`final`,以确保在类定义时变量的值已经确定。 3. **匿名内部类**:匿名内部类是一种没有名称的内部类,它通常用于...
- 如果局部内部类要访问其所在方法的局部变量,该变量必须声明为`final`,否则无法访问。 5. **匿名内部类**: - 匿名内部类是没有名称的内部类,常用于简洁地实现单个接口或继承单个类的情况。 - 匿名内部类...
它们可以访问该方法中的局部变量,但这些变量必须是final的。本地内部类的作用域仅限于定义它的方法或块。 4. **匿名内部类(Anonymous Inner Classes)**:匿名内部类没有名字,它们通常用于实现接口或继承类。在...
局部内部类可以访问方法的局部变量,但这些变量必须声明为final。 - 静态内部类:与普通成员内部类不同,静态内部类可以像普通类一样通过类名直接创建实例,无需外部类的实例。但它不能直接访问外部类的非静态成员...
局部内部类只存在于某个方法、构造器或代码块中,它没有访问修饰符,但能访问方法或代码块内的局部变量以及外部类的所有成员。值得注意的是,如果局部内部类要访问局部变量,这个变量必须被声明为`final`。在`Outer...
这是因为匿名内部类实际上是在其封闭的类或方法的上下文中编译的,因此它可以访问这些局部变量。对于非final变量,它们必须是effectively final的,也就是说,尽管它们在声明时未被final修饰,但在使用时不能重新...
- 局部内部类可以访问它所在代码块的所有局部变量,但这些变量必须是`final`的,因为在内部类的生命周期内,这些变量的值不会改变。 - 示例: ```java public void someMethod(int num) { final int localNum =...
局部内部类可以访问它所在的作用域内的所有变量,包括final修饰的局部变量。 3. **静态内部类**:静态内部类与普通内部类的区别在于,静态内部类可以像普通Java类一样拥有静态成员和静态方法,且不依赖于外部类的...
Java匿名内部类是Java语言中一个独特且强大的特性,它允许我们在不需要定义一个单独的类的情况下创建类的实例。这在处理回调、事件监听、单例模式以及其他需要短时间内定义一个简单类的情况时非常有用。本篇文章将...