zoukankan      html  css  js  c++  java
  • java内部类

    原文链接:https://liushiming.cn/2020/02/25/java-inner-class/

    概述

    内部类是指,一个类是另一个类的成员。java中有四种内部类:

    • 内部类(Nested Inner Class)
    • 静态内部类(Static Nested Class)
    • 局部类(Local Inner Class)
    • 匿名类(Anonymou Inner Classe)

    为什么使用内部类

    使用内部类有几个好处:

    • 内部类可以访问外部类包括private的所有元素(成员和方法)。
    • 内部类更具可读性和可维护性,因为它在逻辑上将相关的类/接口内聚在一个地方。
    • 代码优化:内部类引用外部类的元素时,不需要对象来引用,代码可以更简洁。

    内部类

    下面是一个非静态内部类(nested inner class)示例:

    class Outer {
        // Simple nested inner class
        class Inner {
            public void show() {
                System.out.println("In a nested class method");
            }
        }
    }
    
    class Main {
        public static void main(String[] args) {
            Outer.Inner in = new Outer().new Inner();
            in.show();
        }
    }
    

    结果:

    In a nested class method
    

    非静态的内部类不能有static成员或方法,因为内部类依赖外部类的实例化,所以它不能为自己定义任何静态方法。例如,下面的代码不能编译。

    class Outer {
        // Simple nested inner class
        class Inner {
            public static void foo() {
                System.out.println("inner class static method");
            }
        }
    }
    

    编译预检会报错:

    Inner classes cannot have static declarations
    

    非静态内部类可以访问外部类的staticnon-static成员或方法

    class Outer {
        private String alice = "alice";
        private static String bob = "bob";
    
        public void sayHi() {
            System.out.println("hi " + alice + " and " + bob);
        }
    
        class Inner {
            public void innerSayHi() {
                System.out.println("this is " + alice + " and " + bob);
                sayHi();
            }
        }
    }
    
    class Main {
        public static void main(String[] args) {
            Outer.Inner inner = new Outer().new Inner();
            inner.innerSayHi();
        }
    }
    

    结果:

    this is alice and bob
    hi alice and bob
    

    静态内部类

    静态内部类从技术上来说不算一个内部类,它们就像是外部类的静态成员一样。

    静态内部类仅能访问外部类的static成员或方法:

    class Outer {
        private static Double PI = 3.1415926;
    
        static class Inner {
            public static void accessPi() {
                System.out.println("PI: " + PI);
            }
    
            public void calculateArea(Double radius) {
                System.out.println("the circle area is: " + PI * radius * radius);
            }
        }
    }
    
    class Main {
        public static void main(String[] args) {
            Outer.Inner.accessPi();
            Outer.Inner inner = new Outer.Inner();
            inner.calculateArea(3.0);
        }
    

    结果:

    PI: 3.1415926
    the circle area is: 28.274333400000003
    

    静态和非静态内部类的区别

    主要有以下几点:

    • 静态内部类不需要依赖外部类进行实例化,实例化的语法不一样
    // 非静态内部类实例化  
    Outer.Inner inner = new Outer().new Inner();
    
    // 静态内部类实例化  
    Outer.StaticInner inner = new Outer.StaticInner();
    
    • 静态内部类只能访问外部类的static成员,非静态内部类可以访问外部类的staticnon-static成员或方法
    • 静态内部类从技术上来说不算一个内部类,它们就像是外部类的静态成员一样
    • 静态内部类是唯一一个可以在类这个层级使用static关键字形容的类

    局部类

    在方法内可以定义一个局部类,类似于局部变量,这个类的使用范围仅限此方法内

    public class OuterClass {
        public void sayHi() {
            String alice = "alice";
            class Inner {
                public void sayHi() {
                    System.out.println("hi " + alice + " from inner");
                }
            }
            Inner obj = new Inner();
            obj.sayHi();
        }
    
        public static void main(String args[]) {
            OuterClass outerClass = new OuterClass();
            outerClass.sayHi();
        }
    }
    

    结果:

    hi alice from inner
    

    匿名内部类

    匿名内部类是一个局部类,只是它没有名字。如果只想使用一次局部类,那可以考虑使用匿名内部类。匿名内部类可以在定义的时候同时初始化,使代码变得更简洁。

    以下是oracle官方示例 HelloWorldAnonymousClasses ,其中EnglishGreeting是局部类,englishGreeting为EnglishGreeting的对象,定义和声明是分开的,而frenchGreeting和spanishGreeting是匿名类的对象,定义和声明是在一起的:

    public class HelloWorldAnonymousClasses {
      
        interface HelloWorld {
            public void greet();
            public void greetSomeone(String someone);
        }
      
        public void sayHello() {
            
            class EnglishGreeting implements HelloWorld {
                String name = "world";
                public void greet() {
                    greetSomeone("world");
                }
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("Hello " + name);
                }
            }
          
            HelloWorld englishGreeting = new EnglishGreeting();
            
            HelloWorld frenchGreeting = new HelloWorld() {
                String name = "tout le monde";
                public void greet() {
                    greetSomeone("tout le monde");
                }
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("Salut " + name);
                }
            };
            
            HelloWorld spanishGreeting = new HelloWorld() {
                String name = "mundo";
                public void greet() {
                    greetSomeone("mundo");
                }
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("Hola, " + name);
                }
            };
            englishGreeting.greet();
            frenchGreeting.greetSomeone("Fred");
            spanishGreeting.greet();
        }
    
        public static void main(String... args) {
            HelloWorldAnonymousClasses myApp =
                new HelloWorldAnonymousClasses();
            myApp.sayHello();
        }            
    }
    

    匿名类是一个表达式。匿名类表达式的语法类似于构造函数的调用,只是在代码块中包含一个类定义。一般都是new一个interface:

            HelloWorld frenchGreeting = new HelloWorld() {
                String name = "tout le monde";
                public void greet() {
                    greetSomeone("tout le monde");
                }
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("Salut " + name);
                }
            };
    

    参考资料

    geeksforgeeks - inner class in java
    geeksforgeeks - Static class in Java
    javatpoint - Java static nested class
    javatpoint - Java Inner Classes
    tutorialsPoint - What are method local inner classes in Java?
    oracle - Anonymous Classes

  • 相关阅读:
    Thinkphp M方法出错,D方法却可以
    Composer项目安装依赖包
    wamp httpd-vhosts.conf
    博客园报错 Mixed Content: The page at 'https://i.cnblogs.com/EditPosts.aspx?opt=1' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://upload.cnblogs.com/imageuploa
    Thinkphp js、css压缩类minify
    Thinkphp 不足之处
    Thinkphp 调试方法
    Lavavel 程序报错 MassAssignmentException in Model.php line 452: _token
    Laravel 安装mysql、表增加模拟数据、生成控制器
    Laravel 安装登录模块
  • 原文地址:https://www.cnblogs.com/huahuayu/p/12390353.html
Copyright © 2011-2022 走看看