Java中的内部类怎么用
一、为什么需要内部类?java内部类有什么好处?为什么需要内部类?
首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这
样做可以完成所有你直接实现这个接口的功能。
不过你可能要质疑,更改一下方法的不就行了吗?
的确,以此作为设计内部类的理由,实在没有说服力。
真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题 没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。二、内部类的基本定义在类的内部可以定义成员变量和方法,而且在类的内部也可以定义另一个类,如果类Outer的内部在定义一个类Inner,此时Inner就成为内部类,而Outer则称为外部类。
内部类可以声明为public或private。当内部类声明为public或private,对其访问权限于成员变量和成员方法完全相同。代码如下:package com.se.innerclass;
class Outer {
private String info = "我爱你中国";
class Inner{
public void print() {
System.out.println(info);
}
}
public void fun() {
new Inner().print();
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun();
}
}
输出结果:
以上的程序中可以清楚的发现,Inner类作为Outer类的内部类存在,并且外部类的fun()方法中直接实例化内部类的对象调用方法print(),但是从代码中可以明显发现,内部类的存在实际上破坏了一个类的基本结构,因为类是由属性及方法组成的,所以这是内部类的一个缺点,那么内部类有哪些优点呢,如果把内部类拿到外面来就能发现内部类的优点了。
如下面的代码:package com.se.innerclass;class Outer {
private String info = "我爱你中国";
public void fun() {
new Inner(this).print();
}
public String getInfo(){
return info;
}
}
class Inner{
private Outer outer;
public Inner(Outer outer){
this.outer = outer;
}
public void print() {
System.out.println(outer.getInfo());
}
}
public class InnerClassDemo2 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun();
}
}
以上程序完成了内部类同样的功能,但是但是代码明显比之前的更加复杂,所以内部类的唯一好处就是可以方便的访问外部类的私有属性。三、使用static定义外部类使用static可以声明属性或方法,而使用static也可以声明内部类,用static声明内部类变成了外部类,但是用static声明的内部类不能访问非static的外部类属性。package com.se.innerclass;class Outer{
private static String info = "我爱你中国";
static class Inner{
public void print() {
System.out.println(info);
}
}
}
public class InnerClassDemo3{
public static void main(String[] args) {
new Outer.Inner().print();
}
}
以上程序将info属性定义成了static类型,这样程序中就可以通过static声明的内部类直接访问此static属性,当然,如果此时info属性不是static类型,则编译时将出现以下错误:
’
四、在外部类访问内部类一个内部类除了可以通过外部类访问,也可以直接在其他类当中调用,调用的基本格式为:
外部类.内部类 内部类对象 = 外部类实例.new 内部类()
以上的操作格式中,首先要找到外部类的实例化对象之后才可以通过外部类的实例化对象去实例化内部类对象。
这里我们可以观察到编译之后的内部类的.class文件。
内部类定义之后,生成的.class文件是以Outer$Inner的形式存在的,在Java中只要文件存在$,则在程序中应将其替换为”.”。
在外部访问内部类代码如下:package com.se.innerclass;class Outer{
private String info = "我爱你中国";
class Inner{
public void print() {
System.out.println(info);
}
}
}public class InnerClassDemo4 {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.print();
}
}
五、在方法中定义内部类也可以在方法类定义一个内部类,但是在方法中定义的内部类不能直接访问方法中的参数,如果方法中的参数要想被内部类所访问,则参数前必须加上final关键字。
在方法中定义内部类:package com.se.innerclass;class Outer{
private String info = "我爱你中国";
public void fun(final String temp){
class Inner{
public void print(){
System.out.println(info);
System.out.println(temp);
}
}
new Inner().print();
}
}public class InnerClassDemo5 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun("123");
}
}
六、匿名内部类
在java中处理内部类之外,还有一种匿名内部类。匿名内部类就是指没有一个具体名称的类,此概念是在接口和抽象类的应用上发展起来的,那么匿名内部类有哪些作用呢?
一个简单的操作:package com.se.innerclass;
/**
* 普通实现
* @author wzy
*
*/
interface A {
public void printInfo();
}
class B implements A{
@Override
public void printInfo() {
System.out.println("Hello world!!!");
}
}
class X{
public void fun1(){
this.fun2(new B());
}
public void fun2(A a){
a.printInfo();
}
}
public class NoInnerClassDemo6 {
public static void main(String[] args) {
new X().fun1();
}
}
通过以上的方法可以实现相应的功能,但是现在如果接口实现类只使用一次,那么还有必要单独定义一个子类B吗?很显然是没有必要的,所以此时就可以使用匿名内部类完成,代码修改如下:package com.se.innerclass;
interface A{
public void printInfo();
}
class X{
public void fun1() {
this.fun2(new A(){
@Override
public void printInfo() {
System.out.println("hello world");
}});
}
public void fun2(A a) {
a.printInfo();
}
}
public class NoInnerClassDemo7 {
public static void main(String[] args) {
new X().fun1();
}
}
七、内部类的扩展在接口内部可以添加抽象类,在抽象类内部可以添加接口,由于使用较少,不做过多介绍。
内部类:
(一):定义:
把类定义在另一个类的内部,该类就被称为内部类。
举例:下面用代码进行体现 class Outer {
class Inner {
}
}
(二) 内部类的访问规则
A:可以直接访问外部类的成员,包括私有 B:外部类要想访问内部类成员,必须创建对象(三) 内部类的分类
A:成员内部类 B:局部内部类 C:静态内部类 D:匿名内部类
(1) 成员内部类
成员内部类——就是位于外部类成员位置的类
特点:可以使用外部类中所有的成员变量和成员方法(包括private的)
A 格式:class Outer {
private int age = 20;
//成员位置
class Inner {
public void show() {
System.out.println(age);
}
}
}
class Test {
public static void main(String[] ages) {
//成员内部类是非静态的演示
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
B:创建对象时: //成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
//成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
C:成员内部类常见修饰符:
*****A:
private如果我们的内部类不想轻易被任何人访问,可以选择使用private修饰内部类,这样我们就无法通过创建对象的方法来访问,想要访问只需要在外部类中定义一个public修饰的方法,间接调用。这样做的好处就是,我们可以在这个public方法中增加一些判断语句,起到数据安全的作用。class Outer {
private class Inner {
public void show() {
System.out.println(“密码备份文件”);
}
}
public void method() {
if(你是管理员){
Inner i = new Inner();
i.show();
}else {
System.out.println(“你没有权限访问”);
}
}
}
下面我们给出一个更加规范的写法:class Outer {
private class Inner {
public void show() {
System.out.println(“密码备份文件”);
}
}
//使用getXxx()获取成员内部类,可以增加校验语句(文中省略)
public Inner getInner() {
return new Inner();
}
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.getInner();
inner.show();
}
}
****B:static
这种被 static 所修饰的内部类,按位置分,属于成员内部类,但也可以称作静态内部类,也常叫做嵌套内部类。具体内容我们在下面详细讲解。****D:成员内部类经典题(填空)
请在三个println 后括号中填空使得输出25,20,18class Outer {
public int age = 18;
class Inner {
public int age = 20;
public viod showAge() {
int age = 25;
System.out.println(age);//空1
System.out.println(this.age);//空2
System.out.println(Outer.this.age);//空3
}
}
}
(2) 局部内部类
局部内部类——就是定义在一个方法或者一个作用域里面的类
特点:主要是作用域发生了变化,只能在自身所在方法和属性中被使用
A: 格式class Outer {
public void method(){
class Inner {
}
}
}
B:访问时://在局部位置,可以创建内部类对象,通过对象调用和内部类方法
class Outer {
private int age = 20;
public void method() {
final int age2 = 30;
class Inner {
public void show() {
System.out.println(age);
//从内部类中访问方法内变量age2,需要将变量声明为最终类型。
System.out.println(age2);
}
}
Inner i = new Inner();
i.show();
}
}
C: 为什么局部内部类访问局部变量必须加final修饰呢?
******因为局部变量是随着方法的调用而调用,使用完毕就消失,而堆内存的数据并不会立即消失。所以,堆内存还是用该变量,而该变量已经没有了。为了让该值还存在,就加final修饰。原因是,当我们使用final修饰变量后,堆内存直接存储的是值,而不是变量名。(即上例 age2 的位置存储着常量30 而不是 age2 这个变量名)
(3) 静态内部类我们所知道static是不能用来修饰MT4下载教程类的,但是成员内部类可以看做外部类中的一个成员,所以可以用static修饰,这种用static修饰的内部类我们称作静态内部类,也称作嵌套内部类.
特点:不能使用外部类的非static成员变量和成员方法
解释:非静态内部类编译后会默认的保存一个指向外部类的引用,而静态类却没有。简单理解:即使没有外部类对象,也可以创建静态内部类对象,而外部类的非static成员必须依赖于对象的调用,静态成员则可以直接使用类调用,不必依赖于外部类的对象,所以静态内部类只能访问静态的外部属性和方法。class Outter {
int age = 10;
static age2 = 20;
public Outter() {
}
static class Inner {
public method() {
System.out.println(age);//错误
System.out.println(age2);//正确
}
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
inner.method();
}
}
(4) 匿名内部类一个没有名字的类,是内部类的简化写法
A 格式: new 类名或者接口名() {
重写方法();
}
本质:其实是继承该类或者实现接口的子类匿名对象这也就是下例中,可以直接使用 new Inner() {}.show(); 的原因 == 子类对象.show();interface Inner {
public abstract void show();
}
class Outer {
public void method(){
new Inner() {
public void show() {
System.out.println("HelloWorld");
}
}.show();
}
}
class Test {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
如果匿名内部类中有多个方法又该如何调用呢?Inter i = new Inner() { //多态,因为new Inner(){}代表的是接口的子类对象
public void show() {
System.out.println("HelloWorld");
}
};
B:匿名内部类在开发中的使用我们在开发的时候,会看到抽象类,或者接口作为参数。而这个时候,实际需要的是一个子类对象。如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
————————————————
原文链接:https://blog.csdn.net/weixin_42899466/article/details/82705062
Java中的内部类怎么用的更多相关文章
- Java中的内部类(成员内部类、静态内部类、局部内部类、匿名内部类)
Java中的内部类(成员内部类.静态内部类.局部内部类.匿名内部类) 神话丿小王子的博客主页 我们先看这样一段话:人是由大脑.肢体.器官等身体结果组成.而组成我们人体的心脏它也有自己的属性和行为(血液 ...
- Java 中的内部类
前言 在第一次把Java 编程思想中的内部类这一章撸完后,有点印象.大概知道了什么时内部类,局部内部类,匿名内部类,嵌套内部类.随着时间的推移,自己慢慢的就忘记了,总感觉自己思考的东西不多,于是 看了 ...
- Java中的 内部类(吐血总结)
1. 内部类的作用 内部类是一个独立的实体,可以用来实现闭包:能与外部类通信:内部类与接口使得多继承更完整 2. 内部类的分类 1)普通内部类 类的实例相关,可以看成是一个实例变量.内部类的类名由 “ ...
- 【转】Java中的内部类和匿名类
Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的 ...
- Java学习笔记二十:Java中的内部类
Java中的内部类 一:什么是内部类: (1).什么是内部类呢? 内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. (2).那为什么要将一个类定 ...
- Java中的内部类(回调)
一.内部类的主要作用如下: 1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据 3. 内部类所 ...
- 【Java基础】4、java中的内部类
内部类的分类:常规内部类.静态内部类.私有内部类.局部内部类.匿名内部类. 实例1:常规内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...
- Java中的内部类————以及jdk1.8的lambda表达式
一.内部类学习导图 1>.静态内部类: 使用static修饰符来修饰内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象.因此使用static修饰的内部类被称为静态内部类. publi ...
- Java基础(十五):Java 中的内部类
问:什么是内部类呢? 答:内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 问:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多 ...
随机推荐
- 【归纳】springboot中的IOC注解:注册bean和使用bean
目前了解的springboot中IOC注解主要分为两类: 1. 注册bean:@Component和@Repository.@Service.@Controller .@Configuration 共 ...
- 离线安装gcc_rpm(centos下安装gcc的方法之一)
.解压gcc_rpm.tar.gz (我的CSDN账号下载过) tar -zxvf gcc_rpm.tar.gz .解压完进入文件夹,执行以下命令,挨个执行(如果报依赖错误,就加上"--fo ...
- php 字符转成数字
1.第一种转换方式:在要转换的变量之前加上用括号括起来的目标类型,如 (int):(bool):(float):(string):(array):(object) 2.第二种转换方式:使用3个具体类型 ...
- MyBatis注解开发-@Insert和@InsertProvider(@Select、@SelectProvider雷同)
@Insert和@InsertProvider都是用来在实体类的Mapper类里注解保存方法的SQL语句.不同的是,@Insert是直接配置SQL语句,而@InsertProvider则是通过SQL工 ...
- Git分支,合并,切换分支的使用
1.创建合并分支 在我们每次的提交,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支.HEAD指针严格来说不是指向提交 ...
- v-bin:href 绑定链接
<div id="app06"> <a v-bind:href="URL">我是百度</a> </div> 调用 ...
- c++11 继承构造函数
若基类拥有数量众多的不同版本的构造函数,而派生类中只有一些成员函数,则对于派生类而言,其构造函数就等同于构造基类. struct A { A(int i) {} A(double d, int i) ...
- 使用JAVA如何对图片进行格式检查以及安全检查处理
一.通常情况下,验证一个文件是否图片,可以通过以下三种方式: 1).判断文件的扩展名是否是要求的图片扩展名 这种判断是用得比较多的一种方式,不过这种方式非常的不妥,别人稍微的把一个不是图片的文件的扩展 ...
- mysql中int的长度与值的问题
我们在数据库中设置一个int类型,设置好长度,然后会发现并没有受到长度的限制,这是因为,int值的范围和这个长度根本没有关系. int的存储大小是4个字节(B), 计算机存储单位的换算: 1B=8b ...
- 在Delphi中使用系统对应文件类型的图标
在应用程序的编写中,组合框(ComboBox).列表框(ListBox).等常见的部件,通常不仅要用于显示文字,而且还要显示其与文字相关的图标.在一般的Windows应用程序中,这些图标的显示都要随列 ...