Java内部类详解

简介: 笔记

一、内部类简介


Java语言中允许在一个类(或方法、代码块)的内部定义另一个类,后者称为“内部类”(Inner Classes),也称为“嵌套类”(Nested Classes),封装它的类称为“外部类”。内部类与外部类之间存在 逻辑上的隶属关系,内部类一般只用在封装它的外部类或代码块中使用。


内部类优点:内部类技术使程序结构变得紧凑

内部类缺点:在一定程度上破坏了Java面向对象思想。


(1)内部类的作用

封装。将不想公开的实现细节封装到一个内部类中,内部类可以声明为私有的,只能在所在外 部类中访问。

提供命名空间。静态内部类和外部类能够提供有别于包的命名空间。

便于访问外部类成员。内部类能够很方便访问所在外部类的成员,包括私有成员也能访问。

(2)内部类的分类

图解:1.png



二、成员内部类


定义:成员内部类类似于外部类的成员变量,在外边类的内部,且方法体和代码块之外定义的内部类。


(1)实例成员内部类

特点:实例内部类与实例变量类似,可以声明为公有级别、私有级别、默认级别或保护级别,即4种访问级别都可以,而外部类只能声明为公有或默认级别。

代码如下:

//外部类
public class Outer {
//    外部成员变量
    private int x = 10;
//    外部类方法
    private void print(){
        System.out.println("调用外部类方法。。。。。");
    }
//    测试调用内部类
    public void test(){
        Inner inner = new Inner();
        inner.display();
    }
//    内部类
    class Inner{
//        内部类成员变量
        private int x = 5;
//    内部类方法
        void display(){
    //        访问外部类的成员变量x
            System.out.println("外部成员变量x = "+Outer.this.x);
    //        访问内部类成员变量x
            System.out.println("内部成员变量x = "+this.x);
            System.out.println("内部成员变量x = "+x);
    //        调用外部类的成员方法
            Outer.this.print();
            print();
        }
    }
}

测试代码:

public class HelloWorld {
    public static void main(String[] args) {
//        通过外部类调用外部类
        Outer outer = new Outer();
        outer.test();
        System.out.println("直接访问内部类");
//        直接访问内部类
        Outer.Inner inner = outer.new Inner();
        inner.display();
    }
}

总结:在内部类中this是引用当前内部类对象,若要引用外部类成员变量需要使用“外部类名.this”,如果内部类和外部类它们的成员命名没有冲突情况下,在引 用外部类成员方法时可以不用加“外部类名.this”。


内部类的类型表示“外部类.内 部类”,实例化过程是先实例化外部类,再实例化内部类,outer对象是外部类实例,outer.new Inner()表 达式实例化内部类对象。


(2)静态成员内部类

静态成员内部类与静态变量类似,在声明的时候使用关键字static修饰,静态成员内部类只能访问外部类静态成员。

代码如下:

//外部类
public class View {
//    外部类实例变量
    private int x = 20;
//        外部类静态变量
    private static int staticX = 10;
//    静态成员内部类
    static class Button{
//        内部方法
        void onClick(){
//            访问外部类的静态成员
            System.out.println(staticX);
//            不能访问外部累的非静态成员
//            System.out.println(x);
        }
    }
}

测试代码:

public class HelloWorld {
    public static void main(String[] args) {
//        直接访问内部类
        View.Button button = new View.Button();
        button.onClick();
    }
}

从代码View.Button button = new View.Button()可见,在声明静态内部时采用“内部类.静态内部类”形 式,实例化也是如此形式。


三、局部内部类


局部内部类就是在方法体或代码块中定义的内部类,局部内部类的作用域仅限于方法体或代码块中。局部内部类访问级别只能是默认的,不能是公有的、私有的和保护的访问级别,即不能使用public、 private和protected修饰。局部内部类也不能是静态,即不能使用static修饰。局部内部类可以访问外部 类所有成员。

代码如下:

//外部类
public class Outer {
//    外部类成员变量
    private  int value = 10;
//    外部类方法
    public void add(final int x,int y){
//        局部变量
        int z = 100;
//        自定义内部类
        class Inner{
//            内部类方法
            void display(){
                int sum = x+z+value;
                System.out.println("sum = "+sum);
            }
        }
//        Inner inner = new Inner();
//        inner.display();
//        声明匿名对象
        new Inner().display();
    }
}

测试代码:

public class HelloWorld {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.add(10,15);
    }
}


上述代码在add方法中定义了局部内部类,在内部类中访问了外部类成员变 量value、方法参数x和方法局部变量z,其中方法参数应该声明为final。


四、匿名内部类


匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

为什么要使用匿名内部类:说白了,就是因为想偷懒,不想写太多代码。如果可以,程序员完全可以通过实现接口或者继承抽象类的方式来实现而不用创建匿名内部类。但是使用匿名内部类的优点是显而易见的,可以少些代码,而且代码更加简洁。

匿名内部类的定义的语法格式:

new 实现接口(){
    //匿名内部类类体部分
}
new 父类构造器(实参列表){
  //匿名内部类类体部分
}

因此这两种方式的定义分别对应两种方式,一种是接口,另一种是抽象类。

对于实现接口,由于接口是没有构造函数的,注意这里一定是空参数。

第二种是调用父类的构造器,注意此处可以是空参数,也可以传入参数。

如何使用匿名内部类,代码如下:

第一种情况:实现接口

public interface Product {
    public double getPrice();
    public String  getName();
}

上面代码定义一个接口,接口里面两个抽象方法

public class Anonymous {
    public void test(Product product){
        System.out.println(product.getName()+"--------"+product.getPrice());
    }
    public static void main(String [ ] args ){
        Anonymous as= new Anonymous ();
//方法参数是匿名类
        as.test(new Product() {
            @Override //实现方法
            public double getPrice() {
                return 1234;
            }
            @Override //实现方法
            public String getName() {
                return "caizhengjie";
            }
        });
    }
}

注意:如果匿名内部类在方法中定义,它所访问的参数需要声明为final的。


相关文章
|
29天前
|
Java
java中,剩下的这两个内部类不太好理解!
java中,剩下的这两个内部类不太好理解!
12 0
|
29天前
|
Java 编译器
java中常见的几种内部类,你会几个?(未完)
java中常见的几种内部类,你会几个?(未完)
14 1
|
4月前
|
Java 数据安全/隐私保护
【零基础学Java】—内部类的概念与分类(三十)
【零基础学Java】—内部类的概念与分类(三十)
|
7天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
25 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
9天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
9天前
|
存储 Java
java接口和内部类
java接口和内部类
|
1月前
|
Java 编译器
详解java各种内部类
详解java各种内部类
|
1月前
|
设计模式 Java
JAVA内部类
JAVA内部类
10 1
|
2月前
|
Java
JAVA基础--内部类和静态内部类、单例模式---静态内部类剖析
JAVA--内部类和静态内部类、单例模式---静态内部类剖析
38 9
|
4月前
|
Java
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
40 0