java中的内部类总结

内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类

如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)

显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类

而心脏又在人体当中,正如同是内部类在外部内当中

实例1:内部类的基本结构

//外部类
class Out {private int age = 12;//内部类class In {public void print() {System.out.println(age);}}
}public class Demo {public static void main(String[] args) {Out.In in = new Out().new In();in.print();//或者采用下种方式访问/*Out out = new Out();Out.In in = out.new In();in.print();*/}
}

运行结果:12

从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?

因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点

如同心脏可以直接访问身体的血液,而不是通过医生来抽血

 

程序编译过后会产生两个.class文件,分别是Out.class和Out$In.class

其中$代表了上面程序中Out.In中的那个 .

Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意

  1.开头的Out是为了标明需要生成的内部类对象在哪个外部类当中

  2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变

 

实例2:内部类中的变量访问形式

class Out {private int age = 12;class In {private int age = 13;public void print() {int age = 14;System.out.println("局部变量:" + age);System.out.println("内部类变量:" + this.age);System.out.println("外部类变量:" + Out.this.age);}}
}public class Demo {public static void main(String[] args) {Out.In in = new Out().new In();in.print();}
}

运行结果:

局部变量:14
内部类变量:13
外部类变量:12

从实例1中可以发现,内部类在没有同名成员变量和局部变量的情况下,内部类会直接访问外部类的成员变量,而无需指定Out.this.属性名

否则,内部类中的局部变量会覆盖外部类的成员变量

而访问内部类本身的成员变量可用this.属性名,访问外部类的成员变量需要使用Out.this.属性名

 

实例3:静态内部类

class Out {private static int age = 12;static class In {public void print() {System.out.println(age);}}
}public class Demo {public static void main(String[] args) {Out.In in = new Out.In();in.print();}
}

运行结果:12

可以看到,如果用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性

其次,因为内部类被静态化,因此Out.In可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系)

 

实例4:私有内部类

class Out {private int age = 12;private class In {public void print() {System.out.println(age);}}public void outPrint() {new In().print();}
}public class Demo {public static void main(String[] args) {//此方法无效/*Out.In in = new Out().new In();in.print();*/Out out = new Out();out.outPrint();}
}

运行结果:12

如果一个内部类只希望被外部类中的方法操作,那么可以使用private声明内部类

上面的代码中,我们必须在Out类里面生成In类的对象进行操作,而无法再使用Out.In in = new Out().new In() 生成内部类的对象

也就是说,此时的内部类只有外部类可控制

如同是,我的心脏只能由我的身体控制,其他人无法直接访问它

 

实例5:方法内部类

class Out {private int age = 12;public void Print(final int x) {class In {public void inPrint() {System.out.println(x);System.out.println(age);}}new In().inPrint();}
}public class Demo {public static void main(String[] args) {Out out = new Out();out.Print(3);}
}

运行结果:

3
12

在上面的代码中,我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法

如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义

至于final在这里并没有特殊含义,只是一种表示形式而已

 

6、匿名内部类

 

首先回顾下之前的匿名内部类:  

匿名内部类的格式
  new 接口或者接口名(){
        重写方法
    };

 本质:是该类或者接口的子类对象

匿名内部类方式使用多线程
1、new Thread(){代码…}.start();
2、new Thread(new Runnable(){代码…}).start();

注意://在jdk 1.8以前匿名内部类调用外部类对象的属性或者方法时外部类需要使用final修饰 如下面代码所示:

public class Test1 {public void studay(){System.out.println("进入外部类的方法");}//定义一个内部类class Main {public int i = 10;public synchronized void operationSup(){System.out.println("进入内部类的方法");try {i--;System.out.println("Main print i = " + i);Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {//        final SyncException se=new SyncException();final Test1 a=new Test1();//在jdk 1.8以前匿名内部类调用外部类对象的属性或者方法时外部类需要使用final修饰//定义一个匿名内部类Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {a.studay();}},"t1");t1.start();}
}

当:jdk版本换成1.8以下 final Test1 a=new Test1(); 没有使用final修饰及 Test1 a=new Test();

此时调用外部类方法a.studay();就会报错 所以此时一个内部类中用外部类中的对象,该对象必须要final修饰才能通过;

就那这个代码来说,内部类thread在main方法执行完后不会随着方法被GC回收,而方法中的a(Test1)对象可以看做是一个局部变量,在方法执行完后就会被回收,

而在内部类中却还有继续用这个a对象,所以要用final修饰该对象,使其会在内部类中复制一份副本给内部类使用。当然它的值是不会改变的。

 

转载于:https://www.cnblogs.com/a8457013/p/8080707.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251254.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementPlus关闭弹窗,页面原先滚动条消失

一开始以为是弹窗内容超过一屏引起,改为一屏内也不能解决。 打开控制台,发现弹窗后自动给body标签加上了类el-popup-parent–hidden,关闭后也没去除,因此手动删除该类。 document.getElementsByTagName(body)[0].className ;

在Windows下如何创建虚拟环境(默认情况下)

很多小伙伴平时在使用Python的时候,有的项目需要使用Python2来进行开发,有的项目则是需要Python3来进行开发。当不清楚怎么分开环境的时候,此时两个环境开始打架,彼此傻傻分不清楚。虚拟环境作为隔离的利器应运而生,其…

javascript --- 隐藏内部实现(最小暴露原则)

看下面的一个例子: function doSomething(a) {b a doSomethingElse( a * 2 );console.log( b * 3 ); }function doSomethingElse(a) {return a - 1; }var b;doSomething( 2 ) ; // 15上述代码中的doSomethingElse实际上应该是doSomething的"私有"部分,根据最小暴露…

selenium python 入门-元素定位

环境搭建 安装教程 http://www.testclass.net/selenium_python/install-selenium/ chrome浏览器 还需要下载chrome driver 把下载的chromedriver .exe放到chrome安装目录下的Application目录下和 python所在的安装目录下,比如我的目录是C:\Program Files (x86)\Goog…

ES5程序设计转ES6 笔记

课程链接 1. 立即执行函数 特点:执行结束,立即销毁;独立作用域执行符号()只能跟在表达式后面,不能放在函数声明后分号可以写在前面/后面document为传入实参,doc为形参 ;(function(doc){...co…

DPDK helloworld 源码阅读

在 DPDK Programmers Guides 中的 EAL 一篇中有一个图可以很清晰地看到一个DPDK的应用程序的大致执行思路: 初始化检查CPU支持、微架构配置等完成后,执行main()函数。 第一步是 rte_eal_init(),核心初始化和启动。其中线程使用的是pthread库&…

javascript --- 作用域和闭包

执行环境: // 定义了变量或函数有权访问的其他数据,决定了它们各自的行为 // 每个执行环境都有一个变量对象与之对应,执行环境中所定义的所有变量和函数都保存在变量对象中 // 某个执行环境中的所有代码执行完毕后,该执行环境被销毁,保存在其中的所有变量和函数定义也随之销毁…

异步下载圆形进度条显示进度

圆形进度条参考链接即可:使用css3实现圆形进度条 需求点击下载后遮罩层显示下载进度: 1.圆形进度条参考以上链接,有点小瑕疵,可更改定位距离实现重合。 2.遮罩层: .lbOverlay{display: none;position: fixed;left: 0;…

javascript基本功

隐式类型转换 var a {_default: 0,toString: function () {return a._default} } if (a 1 && a 2 && a 3) {console.log(解) } 访问一个变量的时候进行拦截 var _default 0 Object.defineProperty(window, a, {get() {return _default} }) if (a 1 &am…

深信服笔试,抓兔子

*问题描述:抓兔子n个排成一排的洞,编号为1到n,兔子每天晚上会跳到相邻的一个洞里,小q每天只能白天检查其中的一个洞,小q会告诉你每天检查的洞,分析是否一定能抓到兔子示例:3个洞,第一…

es6 --- 模块

function foo(){var something cool;var another [1, 2, 3];function doSomething() {console.log( something );}function doAnother() {console.log( another.join( " ! " ) );} } // 是一个不明显的闭包,doSomething()和doAnother()保持了foo的内部作用域接下来…

Java之递归遍历目录,修改指定文件的指定内容

EditProperties.java 1 package PropertiesOperation.Edit;2 3 import java.io.File;4 5 /**6 * 替换指定Porpoerties文件中的指定内容7 * 三个参数:8 * filePath:存放properties文件的目录9 * srcStr:需要替换的字符串 10 * desStr&…

学习日志---7

1.复习Linux hadoop hdfs MapReduce基础知识 1,列举linux常用命令 shutdown now reboot mkdir mkdir -p touch filename rm -r filename rm -rf filename vi filename i--->可编辑状态 esc --> : --->wq 保存退出 q! wq! cat grep find ifconfig ping user…

javascript --- 属性描述符

从ES5开始,所有的属性都具备了属性描述符 var myObject {a: 2 };Object.getOwnPropertyDescriptor(myObject, "a"); //{ // value:2, // writable: true, // 可写 // enumerable: true, // 可枚举 // configurble: true // 可配置 //}定义属性…

看了吗网址链接

sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare # -*- coding: utf-8 -*- ""&qu…

JMeter 性能测试进阶实战

课程简介 本课程制作的主要目的是为了让大家快速上手 JMeter,期间穿插了大量主流项目中用到的技术,以及结合当今主流微服务技术提供了测试 Dubbo 接口、Java 工程技术具体实施方案,注重实践、注意引导测试思维、拒绝枯燥的知识点罗列、善于用…

javascript --- 混入

显示混入: function mixin(sourceObj, targetObj){for(var key in sourceObj){ // 遍历source中的所有属性if(!(key in targetObj)) { // 找到targetz中没有的属性targetObj[key] sourceObj[key];}}return targetObj; }var Vehicle {engines: 1,iginition: function() {c…

php源码代目录

ext :存放动态和内建模块的目录,在这里可以找到所有的php官方亏站,并且也可以在这里编写扩展; main:包含php的主要宏定义; pear: PHP扩展与应用库; sapi:包含不同服务器抽象层的代码; TSRM:Zend和PHP的"线程安全资源管理器"目录; Z…

bzoj1231 [Usaco2008 Nov]mixup2 混乱的奶牛——状压DP

题目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id1231 小型状压DP&#xff1b; f[i][j] 表示状态为 j &#xff0c;最后一个奶牛是 i 的方案数&#xff1b; 所以下一个只能是和它相差大于 k 而且不在状态中的奶牛。 代码如下&#xff1a; #include<iostr…

JavaScript高级程序设计阅读笔记

2020-11-15 通过初始化指定变量类型 数字-1 对象null和null的比较&#xff08;不理解&#xff09;使用局部变量将属性查找替换为值查找&#xff08;算法复杂度&#xff09;循环的减值迭代&#xff0c;降低了计算终止条件的复杂度switch快多个变量声明逗号隔开使用数组和对象字面…