内部类你学着累不累

8 篇文章 0 订阅

内部类概述

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

  • 成员内部类
  • 局部内部类
  • 匿名内部类

成员内部类

如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;

class Outer {
	private int num = 10;	
	class Inner {
		public void show() {
			System.out.println(num);
		}
	}
}

class InnerClassDemo {
	public static void main(String[] args) {
		// 访问Inner类的show()方法

        //格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
		Outer.Inner oi = new Outer().new Inner();
		oi.show();
	}
}

而成员内部类的使用,一般来说,在实际开发中是不会这样直接使用的,因为一般内部类就是为了不让外界直接访问的

因此,对Innershow()方法进行保护,使用private为了保证数据的安全性

class Outer {
	private int num = 10;	
	class Inner {
		private void show() {
			System.out.println(num);
		}
	}
    public void GetShow() {
        Inner i = new Inner();
        i.show();
    }
}

class InnerClassDemo {
	public static void main(String[] args) {
		// 访问Inner类的show()方法
        Outer o = new Outer();
        o.GetShow();
	}
}

使用static修饰让数据访问更加方便

  • 被静态修饰的成员内部类只能访问外部类的静态成员
  • 内部类被静态修饰后方法
    • 静态方法
    • 非静态方法
class Outer {
	private int num = 10;
	private static int num2 = 100;
	
	//内部类用静态修饰是因为内部类可以看出是外部类的成员
	public static class Inner {
		public void show() {
			System.out.println(num2);
		}

		public static void show2() {
			System.out.println(num2);
		}		
	}
}

class InnerClassDemo {
	public static void main(String[] args) {
		Outer.Inner oi = new Outer.Inner();
		oi.show();
		oi.show2();
		System.out.println("----------");
		//show2()的另一种调用方式
		Outer.Inner.show2();	
	}
}

思考

填空,要求分别输出30,20,10

		class Outer {
			public int num = 10;
			class Inner {
				public int num = 20;
				public viod show() {
					int num  = 30;
					System.out.println(?);
					System.out.println(?);
					System.out.println(?);
				}
			}
		}
		class Outer {
			public int num = 10;
			class Inner {
				public int num = 20;
				public viod show() {
					int num  = 30;
					System.out.println(num);
					System.out.println(this.num);
					System.out.println(Outer.this.num);
				}
			}
		}
        class InnerClassDemo4 {
            public static void main(String[] args) {
                Outer.Inner oi = new Outer().new Inner();
                oi.show();
            }
        }

注意:

  • 内部类和外部类没有继承关系
  • 通过外部类名限定this对象,(Outer.this

局部内部类

  • 可以直接访问外部类的成员

  • 在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

class Outer {
	private int num  = 10;
	
	public void method() {
		class Inner {
			public void show() {
				System.out.println(num);
			}
		}
        // 创建内部类对象
		Inner i = new Inner();
		i.show();
	}
}

class InnerClassDemo4 {
	public static void main(String[] args) {
        // 创建外部类对象,调用method()方法
		Outer o = new Outer();
		o.method();
	}
}

思考

局部内部类如何访问局部变量?

class Outer {
	private int num  = 10;
	
	public void method() {
		final int num = 20;
		class Inner {
			public void show() {
                // 从内部类中访问本地变量num; 需要被声明为最终类型
				System.out.println(num);
			}
		}
		Inner i = new Inner();
		i.show();
	}
}

class InnerClassDemo5 {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}

局部内部类访问局部变量必须用final修饰

  • 局部变量是随着方法的调用而调用,随着调用完毕而消失。
  • 而堆内存的内容并不会立即消失。所以,我们加final修饰。
  • 加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
  • 在内存中存储的是数据20,所以,我还是有数据在使用。

匿名内部类

匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类

前提

存在一个类或者接口
这里的类可以是具体类也可以是抽象类。

格式

    new 类名或者接口名(){
        重写方法;
    }

本质

是一个继承了该类或者实现了该接口的子类匿名对象。

interface Inter {
	public abstract void show();
}

class Outer {
	public void method() {
        // new 类名或者接口名(){}
		new Inter() {
            // 重写方法
			public void show() {
				System.out.println("show");
			}
		};
	}
}

调用

因此既然new Inter(){};这一坨是一个对象,那么对象调用show()方法还不简单?

// 接口
interface Inter {
	public abstract void show();
}

class Outer {
	public void method() {
        // new 类名或者接口名(){}
		new Inter() {
            // 重写方法
			public void show() {
				System.out.println("show");
			}
		}.show();
	}
}

class InnerClassDemo {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}

如果Inter接口有两个方法,那如何调用?

interface Inter {
	public abstract void show();
	public abstract void show2();
}

class Outer {
	public void method() {

		
		//二个方法的时候
        // 编译看左边,运行看右边
		Inter i = new Inter() { //多态
			public void show() {
				System.out.println("show");
			}
			
			public void show2() {
				System.out.println("show2");
			}
		};
		
		i.show();
		i.show2();
	}
}

class InnerClassDemo {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}

思考

如何使用PersonDemo调用study()方法?

interface Person {
	public abstract void study();
}

class PersonDemo {
	//接口名作为形式参数
	//其实这里需要的不是接口,而是该接口的实现类的对象
	public void method(Person p) {
		p.study();
	}
}

看到此,一般会想到使用具体类来实现接口,在实现类中重写study()方法即可

//实现类
class Student implements Person {
	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

class InnerClassTest {
	public static void main(String[] args) {
		//测试
		PersonDemo pd = new PersonDemo();
		Person p = new Student();
		pd.method(p);
	}
}

这种方然固然可行,那么采用匿名内部类的方式来实现:

class InnerClassTest {
	public static void main(String[] args) {
		// 测试
		PersonDemo pd = new PersonDemo();
        // 匿名内部类的本质是继承类或者实现了接口的子类匿名对象
		pd.method(new Person(){
			public void study() {
				System.out.println("好好学习,天天向上");
			}
		});
	}
}

这种方式占内存较少,占用内存即可及时回收,一般在Android中使用的比较多,因为只使用一次,匿名回收,使用结束即回收

思考

按照要求,补齐代码
    interface Inter { 
    	void show(); 
	}
    class Outer { 
        //补齐代码 
    }
    class OuterDemo {
        public static void main(String[] args) {
              Outer.method().show();
          }
    }
    要求在控制台输出”HelloWorld”
  1. 首先从Outer.method()直接通过类名访问方法,可以判断出是一个静态方法
  2. Outer.method().show()后面还跟着调用show()方法,即可知道Outer.method()返回值是一个对象,对象为Inter
    interface Inter { 
    	void show(); 
	}
    class Outer { 
        // 返回对象为Inter的静态方法
        public static Inter method(){
            // 返回接口对象
            return new Inter(){
                public void show(){
                    System.out.println("HelloWorld");
                }
            }
        }
    }
    class OuterDemo {
        public static void main(String[] args) {
              Outer.method().show();
          }
    }

你学废了吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空 白

停止的只会是自己,你得追逐世界

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值