嵌套类总结归纳

嵌套类总结归纳


提示:以下是本篇文章正文内容,下面案例可供参考

一、概念

嵌套类:重点是嵌套,一个类定义在别的类的内部

//文件名 B.java
//A类在B 类中定义,嵌套
public class B{
    
    
    Class A{
    
    
    }
}

//文件名 D.java
//类C 和 D 是并列的,无从属关系
//这不属于嵌套
class C {
    
    
}

public class D{
    
    

}

二、嵌套类的分类

嵌套类:Nested classes

  • 静态嵌套类: Static nested classes ,即类前面有 static 修饰符
  • 非静态嵌套类:Non-static nested classes,又名内部类,Inner classes
    1. 普通内部类(或者翻译为 成员内部类)
    2. 局部内部类 (Local classes)
    3. 匿名内部类(Anonymous classes)

详细网址:https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

代码展示:

  • 静态嵌套类
public class Outer1{
    
    
      String name;
      //静态嵌套类
      static class Innerq{
    
    
      
      }
}
  • 普通内部类
public class Outer2{
    
    
      String name;
      //普通内部类/成员内部类
      public class Inner2{
    
    
      
      }
}
  • 局部内部类(放在成员方法里面,如一个 for 语句里面,一个 if 语句里面)
public class Outer3{
    
    
     String name;
     //局部内部类
     public void f1(){
    
    
          class Inner3{
    
    
               String name;
          }
     }
}
  • 匿名内部类
public class Outer4{
    
    
		Srting name;
		//匿名内部类
		public void f1(){
    
    
		     new Thread(new Runnable () {
    
    
		         public void run(){
    
    
		            System.out.println("hello");
		         }
				}).start();
		}
}
//这里的 Thread 为一个线程类 ,new Runnable 实现了一个匿名内部类,这个匿名内部类只能使用一次,下次使用只能重新new 

为什么需要嵌套类??

  • 不同的访问权限要求,更细粒度的访问控制
  • 简洁,避免过多的类定义
  • 语言设计过于复杂,较难学习和使用(嵌套类出现缺点)

三、四大嵌套类详细了解

嵌套类学习重点:

  • 嵌套类的语法
  • 嵌套类和其他类的关系
    1. 嵌套类访问外部包围类
    2. 外部包围类访问嵌套类
    3. 第三方类访问嵌套类

匿名内部类:Anonymous classes

  • 没有类名的内部类,必须继承 一个 父类/实现一个父接口
  • 在实例化以后,迅速转型为 父类 / 父接口
  • 这种类型的对象,只能 new 一个对象,之后以对象名字操作
  • 可在普通语句和成员变量赋值时使用内部类
Runnable r = new Runnable(){
    
    
		public void run(){
    
    
				System.out.println("hello");
		}
}

new Thread(r).start();
package com;

public class Outer1 {
    
    
    private String name = "abc";

    //匿名内部类
    public void f1(){
    
    
        String name = "def";
        Runnable r = new Runnable() {
    
    
            //匿名内部类不能定义静态变量,除非是常量
            public final static int a = 5;
            String name = "ghi";
            @Override
            public void run() {
    
    
                System.out.println("hello :"+ name);
                //访问外部成员类的字段
                System.out.println("hello :"+ Outer1.this.name);
            }

            //静态方法不能再匿名内部类定义
            /*public static void f2(){

            }*/
        };

        new Thread(r).start();
        System.out.println(r.getClass().getName());
    }
}

重新对其特点归纳:

  • 没有正式类名的内部类
    编译产生的内部名字: 类名+$+数字编号
  • 没有类名,没有构造函数,能用父类/父接口的构造函数(可带参数)
  • 可以继承、改写、补充父类/父接口的方法
  • 内部不可以重新定义静态成员(变量+方法),常量除外
    final static int a = 5;
  • 可以访问外部包围类的成员变量和方法(包括 private)
  • 如果定义在静态方法中,也只能访问外部包围类的静态成员
  • 没有类名,外部包围类和其他类也无法访问到匿名内部类

局部内部类:Local classes

  • 定义在代码块中的非静态的类,如方法,for 循环,if 语句 等
  • 定义后,即可 创建对象使用
  • 只能活在这个代码块中,代码块结束后,外界无法使用该类
public void f1(){
    
    
     String name = "def";
     class Inner2{
    
    
         public void f2(){
    
    
           System.out.println(name);
           System.out.println(Outer2.this.name);
         }
     }
     Inner2 obj1 = new Inner2();
     obj1.f2();
}

特点:

  • 编译后名称: 外部类名+$+序号+内部类名
  • 可以继承其他的类,或者实现其他接口
  • 非静态的类,不能包含静态成员(变量+方法),除了常量
  • 可以访问外部包围类的成员
  • 如果定义在静态方法,只能访问包围类的静态成员
  • 局部内部类不能是一个接口,即接口不能定义在代码块中

普通内部类:

  • 非static 的类,定义在某个类的成员变量位置
  • 定义后,在类里面均可以使用
public interface Flyable {
    
    
    public void fly();
}

public abstract class Animal {
    
    
    public abstract  void eat();
}

#上面两个一个为接口,一个为抽象类,和下面代码是分开的


public class Outer3 {
    
    
    String name = "aaa";
    public class Bird extends Animal implements Flyable{
    
    
        public final static int a = 3;//常量OK
        @Override
        public void eat() {
    
    
            System.out.println("I can fly");
        }

        @Override
        public void fly() {
    
    
            System.out.println("I can fly" + name);
        }
    }
    public Bird obj = new Bird();
    public void f1(){
    
    
        obj.fly();
        System.out.println(obj.getClass().getName());
        this.name = "bbbb";
        obj.fly();
    }
    public Bird getBird(){
    
    
        return this.obj;
    }
}



特点:

  • 编译后名称:外部类名+$ +内部类名
  • 可以继承其他类,或者实现其他接口
  • 可以用private /default(不写)/ protected /public 控制外界访问
  • 非静态的类,不能包含静态变量 / 方法,除了常量
  • 和外部包围类的实例相关,一个普通内部类实例肯定是在一个外部包围类的实例中,且可以访问外部包围类的所有成员。
  • 在第三方类中,需要先创建外部包围类实例,才能创建普通内部类的实例,不允许单独的普通内部类对象存在!!!

静态嵌套类:

  • 层级和包围类(enclosing class) 的成员变量 / 方法一样
public class Outer1{
    
    
      String name;
      //静态嵌套类
      static class Inner1{
    
    
         String name;
      }
}
  • 第三方只能通过外部包围类才可以访问到静态嵌套类
  • Outer1.Inner1 obj = new Outer1.Inner1();

特点:

  • 需要加修饰符 static
  • 可以定义静态成员和非静态成员
  • 不能直接访问包围类的非静态成员,可以直接访问包围类的静态成员
    可通过包围类对象进行访问非静态成员
  • 外界可以通过静态嵌套类名访问其静态成员,通过对象访问其非静态成员
  • 外界需要通过包围类才可以访问到静态嵌套类,并创建其对象,不需要外部包围类的实例。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

四、变量遮蔽

变量遮蔽: Shadowing

如果嵌套类变量和外部包围类的变量重名

  • 以离得近作为优先原则
  • 优先级高的变量会遮蔽优先级低的变量
  • 外部包围类.this.变量名,可以访问到外部包围类的成员变量
  • 静态嵌套类不能访问非静态变量
  • Java7 以前,匿名内部类和局部内部类只能访问外部包围类的final 成员变量
  • Java 8 以后,匿名内部类和局部内部类可以访问外部包围类的final 成员变量和事实意义上的final 变量(effectively final ,一个变量定义后,再也没有改过)

猜你喜欢

转载自blog.csdn.net/CXgeng/article/details/123425797