内部类和静态内部类

示例

  1. public class OuterClass {
  2. private int numPrivate = 1;
  3. public int numPublic = 2;
  4. public static int numPublicStatic = 3;
  5. private static int numPrivateStatic = 4;
  6. public void nonStaticPublicMethod(){
  7. System.out.println("using nonStaticPublicMethod");
  8. }
  9. private void nonStaticPrivateMethod(){
  10. System.out.println("using nonStaticPrivateMethod");
  11. }
  12. public static void staticPublicMethod(){
  13. System.out.println("using staticPublicMethod");
  14. }
  15. private static void staticPrivateMethod(){
  16. System.out.println("using staticPrivateMethod");
  17. }
  18. class InnerClass{
  19. //Inner class cannot have static declarations
  20. //static int numInnerClass = 4;
  21. //public static void test(){}
  22. int numNonStaticInnerClass = 5;
  23. public void print(){
  24. System.out.println("using InnerClass");
  25. System.out.println("access private field: "+numPrivate);
  26. System.out.println("access public field: "+numPublic);
  27. System.out.println("access public static field: "+numPublicStatic);
  28. System.out.println("access private static field: "+numPrivateStatic);
  29. System.out.println("access numNonStaticInnerClass: "+numNonStaticInnerClass);
  30. nonStaticPrivateMethod();
  31. nonStaticPublicMethod();
  32. staticPrivateMethod();
  33. staticPublicMethod();
  34. }
  35. }
  36. static class StaticNestedClass{
  37. static int numStaticNestedClass = 6;
  38. int numNonStaticNestedClass = 7;
  39. public void print(){
  40. System.out.println("using StaticNestedClass");
  41. System.out.println("access public static field: "+numPublicStatic);
  42. System.out.println("access private static field: "+numPrivateStatic);
  43. System.out.println("access numStaticNestedClass: "+numStaticNestedClass);
  44. System.out.println("access numNonStaticNestedClass: "+numNonStaticNestedClass);
  45. staticPrivateMethod();
  46. staticPublicMethod();
  47. }
  48. }
  49. public static void main(String[] args) {
  50. //内部类实例对象
  51. OuterClass outerClass = new OuterClass();
  52. OuterClass.InnerClass innerClass = outerClass.new InnerClass();
  53. innerClass.print();
  54. System.out.println("=====================");
  55. //静态内部类实例化对象
  56. OuterClass.StaticNestedClass nestedClass = new OuterClass.StaticNestedClass();
  57. nestedClass.print();
  58. }
  59. }

结果

  1. using InnerClass
  2. access private field: 1
  3. access public field: 2
  4. access public static field: 3
  5. access private static field: 4
  6. access numNonStaticInnerClass: 5
  7. using nonStaticPrivateMethod
  8. using nonStaticPublicMethod
  9. using staticPrivateMethod
  10. using staticPublicMethod
  11. =====================
  12. using StaticNestedClass
  13. access public static field: 3
  14. access private static field: 4
  15. access numStaticNestedClass: 6
  16. access numNonStaticNestedClass: 7
  17. using staticPrivateMethod
  18. using staticPublicMethod

静态内部类使用方法

通过外部类访问静态内部类

  1. OuterClass.StaticNestedClass

创建静态内部类对象

  1. OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

内部类的使用方法

必须先实例化外部类,才能实例化内部类

  1. OuterClass outerClass = new OuterClass();
  2. OuterClass.InnerClass innerClass = outerClass.new InnerClass();

两者区别

  1. 内部类, 即便是私有的也能访问,无论静态还是非静态都能访问

    • 可以访问封闭类(外部类)中所有的成员变量和方法
    • 封闭类(外部类)中的私有private成员变量和方法也可以访问
    • 内部类中不可以有静态的变量和静态的方法
  2. 静态内部类

    • 无权访问封闭类(外部类)的中的非静态变量或者非静态方法
    • 封闭类(外部类)中的私有private的静态static成员变量和方法也可以访问
    • 静态内部类中可以有静态的变量和静态的方法
  3. 内部类可以被声明为private, public, protected, or package private. 但是封闭类(外部类)只能被声明为public or package private

特殊情况

  1. public class ShadowTest {
  2. public int x = 0;
  3. class FirstLevel {
  4. public int x = 1;
  5. void methodInFirstLevel(int x) {
  6. System.out.println("x = " + x);
  7. System.out.println("this.x = " + this.x);
  8. System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
  9. }
  10. }
  11. public static void main(String... args) {
  12. ShadowTest st = new ShadowTest();
  13. ShadowTest.FirstLevel fl = st.new FirstLevel();
  14. fl.methodInFirstLevel(23);
  15. }
  16. }

输出结果

  1. x = 23
  2. this.x = 1
  3. ShadowTest.this.x = 0

结论

  1. ShadowTest类中定义了三个名字一样的变量x

    • ShadowTest的成员变量x

    • FirstLevel内部类的成员变量x

    • methodInFirstLevel方法中的参数x

  2. methodInFirstLevel方法中的参数x在内部类FirstLevel的阴影下, 所以在方法methodInFirstLevel中使用x的时候, x指向的是方法的参数x, 此时x的结果为23

  3. 此时this指向的内部类FirstLevel的作用域, 所以this.x的结果是1

  4. ShadowTest.this指向的是ShadowTest的作用域, 此时ShadowTest.this.x的结果是1

为什么使用内部类

  • 这是一种对仅在一个地方使用的类进行逻辑分组的方法:如果一个类仅对另一个类有用,那么将其嵌入该类并将两者保持在一起是合乎逻辑的。
  • 它增加了封装:考虑两个顶级类A和B,其中B需要访问A的成员,如果将A的成员声明为private则B无法访问。通过将类B隐藏在类A中,可以将A的成员声明为私有,而B可以访问它们。另外,B本身可以对外界隐藏。
  • 这可能会导致代码更具可读性和可维护性:在外部类中嵌套小类会使代码更靠近使用位置。

序列化

强烈建议不要对内部类(包括 本地和 匿名类)进行序列化。

如果序列化一个内部类,然后使用其他JRE实现对其进行反序列化,则可能会遇到兼容性问题。

Serialization of inner classes, including local and anonymous classes, is strongly discouraged. When the Java compiler compiles certain constructs, such as inner classes, it creates synthetic constructs; these are classes, methods, fields, and other constructs that do not have a corresponding construct in the source code. Synthetic constructs enable Java compilers to implement new Java language features without changes to the JVM. However, synthetic constructs can vary among different Java compiler implementations, which means that .class files can vary among different implementations as well. Consequently, you may have compatibility issues if you serialize an inner class and then deserialize it with a different JRE implementation. See the section Implicit and Synthetic Parameters in the section Obtaining Names of Method Parameters for more information about the synthetic constructs generated when an inner class is compiled.

Java中内部类和静态内部类的区别的更多相关文章

  1. Java中ArrayList与LinkedList的区别

    Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...

  2. Java中Set Map List 的区别

    java中set map list的区别: 都是集合接口 简要说明 set --其中的值不允许重复,无序的数据结构 list   --其中的值允许重复,因为其为有序的数据结构 map--成对的数据结构 ...

  3. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  4. 转:Java中abstract和interface的区别

    转自:Java中abstract和interface的区别 abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java ...

  5. Java中this与super的区别【6】

    若有不正之处,请多多谅解并欢迎批评指正,不甚感激.请尊重作者劳动成果: 本文原创作者:pipi-changing本文原创出处:http://www.cnblogs.com/pipi-changing/ ...

  6. Java中堆和栈的区别(转)

    栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆.      Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new. ...

  7. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  8. Java中Long与long的区别(转)

    Java中Long与long的区别(转) [本文转载自:http://www.cnblogs.com/bluestorm/archive/2012/04/22/2464739.html] 转载请联系原 ...

  9. java中堆和堆栈的区别

    java中堆和堆栈的区别(一) 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取 ...

随机推荐

  1. Nginx+PHP配置错误,日志:[error] 24324#0: *31 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

    一.问题现象 1.安装nginx.php.php-fpm后,浏览器访问php报错,“File not found”: 二.问题排查 1.检查nginx.php-fpm服务是否正常启动,均正常启动: 2 ...

  2. 百度地图API:使用百度定位

    准备工作: 1.申请百度地图API 2.下载百度地图的SDK 3.将SDK包中的BaiduLBS_Android.jar文件放到,项目里的app/libs里面 4.在src/main目录下创建一个名为 ...

  3. 量化投资学习笔记30——《Python机器学习应用》课程笔记04

    有监督学习 常用分类算法 KNN:K近邻分类器.通过计算待分类数据点,与已知数据中所有点的距离,取距离最小的前K个点,根据"少数服从多数"的原则,将这个数据点划分为出现次数最多的那 ...

  4. cssy元素居中的方法有哪些?

    css的元素居中 各位小伙伴们在努力写网页的时候有没有遇到过这样的一个问题呢? 在写的时候发现他不居中,可是要分分钟逼死强迫症的啊! 别急,我来啦 哈哈哈 今天就带来三种css的元素居中的方法 第一种 ...

  5. 微信小程序app.js中设置公有变量

    初始化GlobalData 在App.js的最上方可以设置GlobalData的初始值. App({ globalData:{ appid: '1wqas2342dasaqwe232342xxxxxx ...

  6. async/await实现图片的串行、并行加载

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 批量复制及执行命令shell脚本

    平时在处理一个或几个机器运行环境时,一个机器一个机器处理也能接受,但是如果是一批机器,几十或几百台,要是一台一台去安装环境,光是输入同一的命令,估计你自己都想吐,所有聪明的人会想一些偷懒的办法,确实可 ...

  8. SpringBoot2整合Redis缓存

    遵循SpringBoot三板斧 第一步加依赖 <!-- Redis --> <dependency> <groupId>org.springframework.bo ...

  9. PHP网络爬虫实践:抓取百度搜索结果,并分析数据结构

    百度的搜索引擎有反爬虫机制,我先直接用guzzle试试水.代码如下: <?php /** * Created by Benjiemin * Date: 2020/3/5 * Time: 14:5 ...

  10. 大多数项目中会用到的webpack小技巧

    原文地址 本文是作者对自己所学的webpack技巧的总结,在没有指定特殊情况下适用于webpack 3.0版本. 进度汇报 使用webpack --progress --colors这样可以让编译的输 ...