面向对象:13、内部类

很多时候我们创建类的对象的时候并不需要使用很多次,每次只使用一次,这个时候我们就可以使用内部类了。

1、内部类概述

内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

内部类不是在一个java源文件中编写俩个平行的俩个类,而是在一个类的内部再定义另外一个类。 我们可以把外边的类称为外部类,在其内部编写的类称为内部类。

内部类分为四种:

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类

2、成员内部类(实例内部类、非静态内部类)

定义一个内部类(成员内部类中不能写静态属性和方法)

//在A类中申明了一个B类,此B类就在A的内部,并且在成员变量的位置上,所以就称为成员内部类
public class Outer {private int id;public void out(){System.out.println("这是外部类方法");}class Inner{public void in(){System.out.println("这是内部类方法");}}
}

实例化内部类(实例化内部类,首先需要实例化外部类,通过外部类去调用内部类)

public class Outer {private int id;public void out(){System.out.println("这是外部类方法");}class Inner{public void in(){System.out.println("这是内部类方法");}}
}
public class Test{public static void main(String[] args) {//实例化成员内部类分两步//1、实例化外部类Outer outObject = new Outer();//2、通过外部类调用内部类Outer.Inner inObject = outObject.new Inner();//测试,调用内部类中的方法inObject.in();//打印:这是内部类方法}
}

成员内部类的作用

访问外部类的所有属性(这里的属性包括私有的成员变量,方法)

public class Outer {private int id;public void out(){System.out.println("这是外部类方法");}class Inner{public void in(){System.out.println("这是内部类方法");}//内部类访问外部类私有的成员变量public void useId(){System.out.println(id+3);。}//内部类访问外部类的方法public void useOut(){out();}}
}
public class Test{public static void main(String[] args) {//实例化成员内部类分两步//1、实例化外部类Outer outObject = new Outer();//2、通过外部类调用内部类Outer.Inner inObject = outObject.new Inner();//测试inObject.useId();//打印3,因为id初始化值为0,0+3就为3,其中在内部类就使用了外部类的私有成员变量id。inObject.useOut();//打印:这是外部类方法}
}

如果内部类中的变量名和外部类的成员变量名一样,要通过创建外部类对象 "."属性来访问外部类属性,通过this.属性访问内部类成员属性

public class Outer {private int id;//默认初始化0public void out(){System.out.println("这是外部类方法");}class Inner{private int id=8; //这个id跟外部类的属性id名称一样。public void in(){System.out.println("这是内部类方法");}public void test(){System.out.println(id);//输出8,内部类中的变量会暂时将外部类的成员变量给隐藏//如何调用外部类的成员变量呢?通过Outer.this,想要知道为什么能通过这个来调用,就得明白下面这个原理//想实例化内部类对象,就必须通过外部类对象,当外部类对象来new出内部类对象时,会//把自己(外部类对象)的引用传到了内部类中,所以内部类就可以通过//Outer.this来访问外部类的属性和方法,到这里,你也就可以知道为什么内部类可以访问外部类//的属性和方法,这里由于有两个相同的//属性名称,所以需要显示的用Outer.this来调用外部类的属性,平常如果属性名//不重复,那么我们在内部类中调用外部类的属性和方法时,前面就隐式的调用了Outer.this。System.out.println(Outer.this.id);//输出外部类的属性id。也就是输出0}}
}

3、静态内部类

static修饰的内部类就叫静态内部类

static一般只修饰变量和方法,平常不可以修饰类,但是内部类却可以被static修饰

1)static修饰成员变量:整个类的实例共享静态变量

2)static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修饰的方法或属性

3)被static修饰了的成员变量和方法能直接被类名调用

4)static不能修饰局部变量

public class StaticInnerClassTest {private String name;private static int age;public void run(){}public static void go(){}//外部类访问静态内部类public void test(){StaticInnerClass sic = new StaticInnerClass(); //静态的内部类不需要依赖外部类,所以不用thissic.name = "tom";sic.test1("jack");StaticInnerClass.age=10;StaticInnerClass.test2("xixi");}private static class StaticInnerClass{private String name;private static int age;public void test1(String name){System.out.println(name);System.out.println(this.name);System.out.println(StaticInnerClass.age);System.out.println(StaticInnerClassTest.age);//System.out.println(StaticInnerClassTest.this.name);静态类不能访问非静态属性StaticInnerClassTest.go();//StaticInnerClassTest.this.run();静态类不能访问非静态方法}public static void test2(String name){//只能访问自己和外部类的静态属性和方法System.out.println(name);//System.out.println(this.name);静态方法里面连自己类的非静态属性都不能访问System.out.println(StaticInnerClass.age);System.out.println(StaticInnerClassTest.age);//System.out.println(StaticInnerClassTest.this.name);静态方法不能访问非静态属性StaticInnerClassTest.go();//StaticInnerClassTest.this.run();静态方法不能访问非静态方法}}
}
  • 内部类能够调用外部类的方法和属性,在静态内部类中就行了,因为静态内部类没有了指向外部类对象的引用。除非外部类中的方法或者属性也是静态的。这就回归到了static关键字的用法。

  • 静态内部类能够直接被外部类给实例化,不需要使用外部类对象

Outer.Inner inner = new Outer.Inner();

  • 静态内部类中可以声明静态方法和静态变量,但是非静态内部类中就不可以声明静态方法和静态变量

4、局部内部类

  • 局部内部类是在一个方法内部声明的一个类
  • 局部内部类中可以访问外部类的成员变量及方法
  • 局部内部类中如果要访问该内部类所在方法中的局部变量,那么这个局部变量就必须是final修饰的
public class Outer {private int id;//在method01方法中有一个Inner内部类,这个内部类就称为局部内部类public void method01(){class Inner{public void in(){System.out.println("这是局部内部类");}}}
}

在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰

为什么需要使用final?

final修饰变量:变为常量,会在常量池中放着,逆向思维想这个问题,如果不实用final修饰,当局部内部类被实例化后,方法弹栈,局部变量跟着消失,这个时候局部内部类对象再想去调用该局部变量,就会报错,因为该局部变量已经没了,当局部变量用final修饰后,就会将其加入常量池中,即使方法弹栈了,该局部变量还在常量池中呆着,局部内部类才能够调用。

所以局部内部类想要调用局部变量时,需要使用final修饰,不使用,编译无法通过

public class Outer {private int id;public void method01(){final int cid = 3; //这个就是局部变量cid。要让局部内部类使用,就得变为final并且赋值,如果不使用final修饰,就会报错class Inner{//内部类的第一个方法public void in(){System.out.println("这是局部内部类");}//内部类中的使用局部变量cid的方法public void useCid(){System.out.println(cid);}}}
}

局部内部类不能通过外部类对象直接实例化,而是在方法中实例化出自己来,然后通过内部类对象调用自己类中的方法

public class Outer {private int id;public void out(){System.out.println("外部类方法");}public void method01(){class Inner{public void in(){System.out.println("这是局部内部类");}}//关键在这里,如需要在method01方法中自己创建内部类实例,然后调用内部类中的方法,等待外部类调用method01方法,就可以执行到内部类中的方法了。Inner In = new Inner();In.in();}
}

5、匿名内部类

匿名内部类是最常用的一种内部类。

什么是匿名对象?

如果一个对象只要使用一次,那么我们就是需要new Object().method()。 就可以了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。

匿名内部类跟匿名对象是一个道理:

匿名对象:我只需要用一次,那么我就不用声明一个该类型变量来保存对象了

匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。不然先写出一个内部类的全部实现来,然后就调用它一次,就会导致资源的浪费

  1. 匿名内部类需要依托于其他类或者接口来创建
    如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
    如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
  2. 匿名内部类的声明必须是在使用new关键字的时候
    匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
main:
A a = new A(){//实现A中的抽象方法//或者重写A中的普通方法
};
注:这个大括号里面其实就是这个内部类的代码,只不过是声明该内部类的同时就是要new创建了其对象,
并且不能反复使用,因为没有名字。例如:
B是一个接口,依托于B接口创建一个匿名内部类对象B b = new B(){//实现B中的抽象方法
};
  1. 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字
  2. 匿名内部中,我们不能写出其构造器,因为没有名字
  3. 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)

面向对象:13、内部类相关推荐

  1. java(13)内部类

    内部类就是定义在类内部的类,可以使java具备为普通类实现多重继承的能力. 非静态内部类,局部内部类,静态内部类,匿名内部类 非静态内部类: package 内部类;class Wai5 {int i ...

  2. Java面向对象(OOP)--内部类(匿名内部类)

    1. 匿名内部类 没有(或者不需要)命名来初始化类,就称为匿名内部类. 在这四种内部类中,以后的工作可能遇到最多的是匿名内部类,所以说匿名内部类是最常用的一种内部类. 什么是匿名对象? 如果一个对象只 ...

  3. java编程笔记8 面向对象三 内部类

    2011-03-03 22:47 a)       匿名类(区别于匿名对象) 没有明确的类定义格式,是指类的定义和类的对象的创建合并在一起的情况. 匿名类属于一个唯一的对象,在生成接口的同时定义匿名类 ...

  4. Day16-01 P71 面向对象12什么是多态 P72 对象13:instanceof和类型转换 P73 static关键字详解 P74 抽象类 P75 接口的定义与实现 P76N种内部类

    Day16-01 P71 面向对象12:什么是多态 //父类Person package com.oop.demo06;public class Person {public void run(){S ...

  5. java 面向对象内部类

    1.内部类概念:将一个类定义在另一个类的内部,该类就称为内部类 类中定义的内部类特点 1) 内部类作为外部类的成员,可以直接访问外部类的成员 (包括 private 成员),反之则不行. 2) 内部类 ...

  6. 黑马程序员_java基础笔记(03)...面向对象

    1:面向对象的概念,2 : 类和对象的关系,3 : 封装,4 : 构造函数,5 : this关键字,6 : static关键字, 7 : 单例设计模式,8 : 继承,9 : 抽象类,10 : 接口,1 ...

  7. java程序设计清考_面向对象程序设计(Java)-题库

    <面向对象程序设计(Java)-题库>由会员分享,可在线阅读,更多相关<面向对象程序设计(Java)-题库(33页珍藏版)>请在金锄头文库上搜索. 1.面向对象程序设计 (ja ...

  8. 第三次学JAVA再学不好就吃翔(part43)--局部内部类访问局部变量

    学习笔记,仅供参考 面向对象 局部内部类访问局部变量 啥叫局部内部类? 局部内部类是指在方法中定义的内部类. 举个例子(访问局部内部类) 局部内部类: class InnerTest1 {public ...

  9. 跟着王进老师学开发Python篇第四季:面向对象基础篇-王进-专题视频课程

    跟着王进老师学开发Python篇第四季:面向对象基础篇-772人已学习 课程介绍         本季课程为Python面向对象基础篇,内容包含:面向对象的介绍.创建类和实例化.实例变量和实例方法.类 ...

  10. java基础总结(小白向)

    java入门基础总结(小白向) 1.类和对象的理解 ​ 理解类和对象对应学习Java尤其重要,可以说类和对象贯穿整个Java语言.我们先给出类和对象比较官方的介绍. ​ 类:具有相同属性和方法的一组对 ...

最新文章

  1. 你想带一顶什么样的硕士帽(转载)
  2. PHP设置页面显示编码
  3. git/github使用完整教程(1)基础
  4. 去哪儿-04-iconsDev
  5. shell按照时间排序_【经典排序】希尔排序
  6. LeetCode(1046)——最后一块石头的重量(JavaScript)
  7. Exploit Kit攻击工具包流量锐减96%!这段时间究竟发生了什么?
  8. 【转】java获取当前路径的几种方法
  9. 单机到集群的WEB架构演变
  10. WPF-StackPanel面板
  11. 阿里巴巴代码扫描插件
  12. win10开启自带wifi共享操作步骤
  13. 第三方支付平台如何对接?
  14. 刚性捆绑,无线运营新模式
  15. 豆瓣top250-词云案例
  16. Quartus联合modelsim的ip核仿真——以FIFO为例——(报错问题解决)
  17. 概率论中的矩母函数(MGF)
  18. Golang之Shadowed Variables(幽灵变量)
  19. macOS安装homebrew与更新gcc
  20. pycharm连接服务器方法

热门文章

  1. 2022年通信专业技术人员职业水平考试
  2. grafana+alertmanager实现微信报警
  3. Dubbo与Dubbox
  4. 三菱FX2NPLC 主控指令MC和主控指令清除MCR指令
  5. java dns缓存清理_JVM DNS缓存问题
  6. 用java把通达信导出的交易记录文件高速批量导入mysql数据库
  7. 小提琴图解读 - 统计学
  8. Gnuradio+uhd驱动软件安装流程
  9. 2019算法面经汇总
  10. Map训练(三国武力值)