内部类使用外部类:
内部类可以随意使用外部类的所有方法和变量
外部类使用内部类有有种方式:
间接方式: 在外部类的方法当中, 创建内部类对象, 使用内部类; 然后 main 只是调用外部类的方法.
直接方式: 格式: 外部类名称. 内部类名称 对象名 = new 外部类名称 ().new 内部类名称 ();
代码举例
- package demo02;
- public class Body { // 外部类
- public class Heart { // 成员内部类
- // 内部类的方法
- public void beat() {
- System.out.println("心脏跳动: 蹦蹦蹦!");
- // 内部类中可以访问外部类的任何属性和方法
- System.out.println("我叫:" + name); // 正确写法! 访问外部类的私有属性
- }
- }
- // 外部类的成员变量
- private String name;
- // 外部类的方法
- public void methodBody() {
- System.out.println("外部类的方法");
- // 创建内部类对象, 之后使用内部类方法
- new Heart().beat();
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
定义测试类
- package demo02;
- public class BodyTest {
- public static void main(String[] args) {
- Body body = new Body(); // 外部类的对象
- // 通过外部类的对象, 调用外部类的方法, 里面间接在使用内部类 Heart
- body.methodBody();
- System.out.println("=====================");
- // 按照公式写:
- Body.Heart heart = new Body().new Heart();
- heart.beat();
- }
- }
代码执行后的结果
内部 / 外部类的同名变量访问
如果外部类和内部类出现了重名问题, 我们如果需要在内部类方法中访问对应的变量. 格式如下:
访问内部类的局部变量 格式: 直接写上变量名称
访问内部类的成员变量 格式: this. 变量名称
访问外部类的成员变量 格式: 外部类名称. this. 变量名称
- package demo02;
- public class Outer {
- int num = 10; // 外部类的成员变量
- public class Inner /*extends Object*/ {
- int num = 20; // 内部类的成员变量
- public void methodInner() {
- int num = 30; // 内部类方法的局部变量
- System.out.println(num); // 访问局部变量, 就近原则
- System.out.println(this.num); // 访问内部类的成员变量
- System.out.println(Outer.this.num); // 访问外部类的成员变量
- }
- }
- }
局部内部类
如果一个类是定义在一个方法内部的, 那么这就是一个局部内部类."局部": 只有当前所属的方法才能使用它, 出了这个方法外面就不能用了.
定义格式:
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称 (参数列表) {
class 局部内部类名称 {
// ...
}
}
}
类的权限修饰符:
public> protected> (default)> private
定义一个类的时候, 权限修饰符规则:
外部类: public / (default)
成员内部类: public / protected / (default) / private
局部内部类: 什么都不能写
- class Outer {
- public void methodOuter() {
- class Inner { // 局部内部类
- int num = 10;
- public void methodInner() {
- System.out.println(num); // 10
- }
- }
- // 局部 只有当前所属方法才能使用他
- Inner inner = new Inner();
- inner.methodInner();
- }
- }
局部内部类的有效 final 问题
- package demo03;
- /*
- 局部内部类, 如果希望访问所在方法的局部变量, 那么这个局部变量必须是 [有效 final 的] .
- 备注: 从 Java 8 + 开始, 只要局部变量事实不变, 那么 final 关键字可以省略.
- 原因:
- 1. new 出来的对象在堆内存当中.
- 2. 局部变量是跟着方法走的, 在栈内存当中.
- 3. 方法运行结束之后, 立刻出栈, 局部变量就会立刻消失.
- 4. 但是 new 出来的对象会在堆当中持续存在, 直到垃圾回收消失.
- */
- public class MyOuter {
- public void methodOuter() {
- int num = 10; // 所在方法的局部变量
- class MyInner {
- public void methodInner() {
- System.out.println(num);
- }
- }
- }
- }
匿名内部类 (重点)
匿名内部类
匿名内部类是内部类的简化写法. 它的本质是一个 带具体实现的父类或者父接口的 匿名的子类对象. 开发中, 最常用到的内部类就是匿名内部类了.
前提
匿名内部类必须继承一个父类或者实现一个父接口.
格式
对格式进行解析:
new 代表创建对象的动作
接口名称就是匿名内部类需要实现哪个接口
{...} 这才是匿名内部类的内容
另外还要注意几点问题:
匿名内部类, 在 [创建对象] 的时候, 只能使用唯一一次. 如果希望多次创建对象, 而且类的内容一样的话, 那么就需要使用单独定义的实现类了.
匿名对象, 在 [调用方法] 的时候, 只能调用唯一一次. 如果希望同一个对象, 调用多次方法, 那么必须给对象起个名字.
匿名内部类是省略了 [实现类 / 子类名称] , 但是匿名对象是省略了 [对象名称] 强调: 匿名内部类和匿名对象不是一回事!!!
代码举例
定义接口
- package demo03;
- public abstract class FlyAble {
- public abstract void fly();
- }
定义匿名内部类
- package demo03;
- public class InnerDemo {
- public static void main(String[] args) {
- /*1. 等号右边: 是匿名内部类, 定义并创建该接口的子类对象
- 2. 等号左边: 是多态赋值, 接口类型引用指向子类对象 */
- FlyAble f = new FlyAble() {
- public void fly() {
- System.out.println("我飞了~~~");
- }
- };
- // 调用 fly 方法, 执行重写后的方法
- f.fly();
- }
- }
通常在方法的形式参数是接口或者抽象类时, 也可以将匿名内部类作为参数传递. 代码如下:
- package demo03;
- public class InnerDemo2 {
- public static void main(String[] args) {
- /* 创建匿名内部类, 直接传递给 showFly(FlyAble f) */
- showFly(new FlyAble() {
- public void fly() {
- System.out.println("我飞了~~~");
- }
- });
- }
- public static void showFly(FlyAble f) {
- f.fly();
- }
- }
代码执行后的结果
来源: http://www.bubuko.com/infodetail-3319859.html