内部类
1.内部类的概述:把类定义在其他类的内部
举例:在类A中定义了一个类B,类B就是内部类
2.内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有的
外部类要访问内部类的成员,必须创建对象
class Outer{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
public void fun(){
// show();
//创建内部类
Inner inner = new Inner();
inner.show();
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
Outer outer = new Outer();
// outer.show();
outer.fun();
}
}
3.按照内部类在类中的位置不同,可以分为如下两种格式:
成员位置(成员内部类)
class Outer2{
//定义在成员的位置上(成员内部类)
class Inner2{
}
}
局部位置(局部内部类)
class Outer2{
public void fun(){
//定义在局部范围内(局部内部类)
class Inner3{
}
}
}
成员内部类
1.成员内部类定义在外部类的成员方法位置上
2.外界如何创建成员内部类对象
格式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
class Outer3{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
}
public class InnerClassDemo3 {
public static void main(String[] args) {
//需求:我现在要想在测试类中访问到Inner类中的show方法,咋办,就必须得创建对象
//Inner inner3 = new Inner(); 错误写法
//正确创建成员内部类对象的格式
//外部类名.成员内部类名 对象名 = new 外部类名().new 成员内部类名();
Outer3.Inner oi3 = new Outer3().new Inner();
oi3.show();
//这样写也可以
Outer3 outer3 = new Outer3();
Outer3.Inner inner = outer3.new Inner();
inner.show();
}
}
3.成员内部类的修饰符:
1)被private修饰,其他类不能直接创建成员内部类的对象,
要想使用被private修饰的成员内部类的成员,必须在外部类中间接的创建对象
class Outer4{
private int num = 200;
private class Inner4{
public void fun(){
System.out.println(num);
}
}
public void show(){
//同一个类中,private失效了,透明的
Inner4 inner4 = new Inner4();
inner4.fun();
}
}
public class InnerClassDemo4 {
public static void main(String[] args) {
//当成员内部类被private修饰,其他类不能直接创建内部类的对象,
// Outer4.Inner4 oi4 = new Outer4().new Inner4(); 报错
//要想使用被private修饰的内部类成员,必须在本类中间接的创建对象调用
Outer4 outer4 = new Outer4();
outer4.show();
}
}
2)被static修饰,只能访问外部类的静态成员
当成员内部类是被static修饰的时候,出现了另外的一种创建内部类的方式
格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
class Outer4{
// private int num = 200;
private static int num = 200;
static class Inner4{
public static void fun(){
System.out.println(num); //静态的只能访问静态的
}
}
}
public class InnerClassDemo4 {
public static void main(String[] args) {
//当成员内部类是被static修饰的时候,不能想原来那样创建内部类对象
Outer4.Inner4 oi4 = new Outer4.Inner4();
oi4.fun();
//直接通过类名直接调用,但是内部类的方法要是静态的
Outer4.Inner4.fun();
}
}
4.练习题
class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(?); System.out.println(??); System.out.println(???); } } } 在控制台分别输出:30,20,10
代码实现:
class Outer5 {
public int num = 10;
class Inner5 {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
//报错。外部类和内部类的不是继承关系,没有super关系
// System.out.println(super.num); 错误写法
System.out.println(new Outer5().num); //10
System.out.println(Outer5.this.num); //10
}
}
}
public class InnerClassDemo5 {
public static void main(String[] args) {
//创建内部类对象
Outer5.Inner5 oi5 = new Outer5().new Inner5();
oi5.show();
}
}
补充知识:
类名.this一般用于内部类调用外部类的对象时使用,因为内部类使用this.调用的是内部类的成员。为了区分,所以使用 类名.this来加以区别
局部内部类
1.局部内部类定义外部类的成员方法中
2.局部内部类可以访问外部类中所有成员
class Outer6{
private int num = 10;
public void fun(){
int num2 = 20;
class Inner6{
int num3 = 300;
public void show(){
System.out.println(num);
System.out.println(num2);
System.out.println(num3);
}
}
}
}
3.要想使用局部内部类中的方法,在定义局部内部类的成员方法中创建局部内部类对象进行调用方法
class Outer6{
private int num = 10;
public void fun(){
int num2 = 20;
class Inner6{
int num3 = 300;
public void show(){
System.out.println(num);
System.out.println(num2);
System.out.println(num3);
}
}
//要想使用局部内部中的方法,在定义局部类的成员方法中,创建局部内部类对象调用方法
Inner6 inner6 = new Inner6();
inner6.show();
}
}
public class InnerClassDemo6 {
public static void main(String[] args) {
Outer6 outer6 = new Outer6();
outer6.fun();
}
}
4.在局部内部类中引用的本地的变量必须是最终变量或者实际上的最终变量。通过反编译工具观察发现,存在局部内部类的方法中定义的局部变量自动加上final关键字(JDK1.8之后)
为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用这个变量。为了让数据还能继续被使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量值
class Outer6{
private int num = 10;
public void fun(){
int num2 = 20;
class Inner6{
int num3 = 300;
public void show(){
//在局部内部类中引用的本地的变量,必须是最终变量,或者是实际上的变量
//通过反编译工具观察发现,存在局部内部类的方法中定义的变量自动加上了final关键字
//JDK1.8之后自动加上final关键字
// num2 = 22; 不能改变值
System.out.println(num);
System.out.println(num2);
System.out.println(num3);
}
}
//要想使用局部内部中的方法,在定义局部类的成员方法中,创建局部内部类对象调用方法
Inner6 inner6 = new Inner6();
inner6.show();
}
}
public class InnerClassDemo6 {
public static void main(String[] args) {
Outer6 outer6 = new Outer6();
outer6.fun();
}
}