它名叫阿福,整天跟着我
在我最最难过的时候
一、内部类
1、基础
把类定义在其他类的内部,这个类就被称为内部类
class Outer{
class Inner{
}
}
2、特点
1、内部类可以直接访问外部类的成员,包括私有
2、外部类要访问内部类的成员,必须创建对象(要在方法内创建,否则是成员变量)
class Outer {
private int num = 20;
class Inner {
int num2 = 200;
public void show() {
//直接访问外部类私有成员
System.out.println(num);
}
}
public void show2(){
//创建内部类对象,调用内部类成员
Inner inner = new Inner();
System.out.println(inner.num2);
inner.show();
// System.out.println(num2);
}
}
3、成员内部类
按照内部类在类中定义的位置不同,可以分为如下两种格式:
1、成员位置(成员内部类)
2、局部位置(局部内部类)
class Outer2{
//定义在成员位置,叫做成员内部类
class Inner{
}
public void show(){
//定义在局部位置,叫做局部内部类
class Inner2{
}
}
}
4、外部调用内部类
同样需要依靠创建内部类对象
1、普通内部类
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
2、静态内部类
外部类名.内部类名 对象名 = new 外部类名.内部对象
此时内部类属性的静态,通过外部类名直接调用内部类构造方法
Outer.Inner oi = new Outer.Inner();
5、内部类常见修饰符
1、private 为了保证数据的安全性
2、static 为了让数据访问更方便
private 修饰的内部类只能在外部类中调用,无法在外部创建实例
//private 内部类
class Body{
private class Heart{
public void bloodXunHuan(){
System.out.println("提供血液循环");
}
}
public Heart show(){
私有的在类内部都可以随意访问,所以此处可以创建他的对象
Heart heart = new Heart();
heart.bloodXunHuan();
return heart;
//利用返回值,试图在外部拿到这个private类(实际上也是不行)
}
}
static 修饰的内部类需要注意外部创建对象的格式,并且调用内部类方法更加方便
//static 内部类
class Body{
public static class Heart{
public static void bloodXunHuan(){
System.out.println("提供血液循环");
}
}
public void show(){
Heart heart = new Heart();
heart.bloodXunHuan();
}
}
public class InnerClassDemo4 {
public static void main(String[] args) {
//当内部类被静态修饰后,访问的格式就变了:
//外部类名.内部类名 对象名 = new 外部类名.内部对象
Body.Heart bh = new Body.Heart();
bh.bloodXunHuan();
//调用bloodXunHuan()另一种方式 链式编程
new Body.Heart().bloodXunHuan();
//当方法也是static时,可以不经过对象,直接通过内部类名调用方法
Body.Heart.bloodXunHuan();
6、练习
/*
在控制分别输出:30,20,10
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(???);
}
}
}
注意:内部类与外部类没有继承关系
*/
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
//指向当前内部类对象
System.out.println(this.num);
//第一种方式,创建外部类对象,访问成员变量
System.out.println(new Outer().num);
//第二种方式,理解为 this Outer 的 num 更好理解
System.out.println(Outer.this.num);
}
}
7、局部内部类
1、可以直接访问外部类的成员
2、可以方法内创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
class Outer {
private int num = 10;
public void show(){
int num2 = 100;
class Inner{
int num3 = 200;
public void show(){
// num2 = 400;
// 不可以,jdk1.8之后会自动在局部方法上的局部变量添加final
System.out.println(num3);
}
}
num2 = 500;
System.out.println(num2);
Inner inner = new Inner();
inner.show();
}
// 不可以
// Inner i = new Inner();
}
二、匿名内部类
匿名内部类:
就是内部类的简化写法。
前提:
存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
new 类名或接口名(){
重写方法;
};
1、例一
interface Inner{
public abstract void show();
public abstract void show2();
}
class Outer{
public void fun(){
//匿名内部类调用方法show
new Inner(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
}.show();
//匿名内部类调用方法show2
new Inter(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
}.show2();
//问题:如果我这个接口有很多方法,还要使用匿名内部类的形式就很麻烦
//因为每次调用里面实现的方法,多需要创建一个内部类,怎么改进?
System.out.println("====改进版=======");
Inter i = new Inter(){
//多态
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
};
i.show();
i.show2();
System.out.println("============");
}
}
public class InnerClassDemo {
public static void main(String[] args) {
Outer o = new Outer();
outer.fun();
}
}
2、例二
interface Person8{
public abstract void study();
}
class PersonDemo8{
//当接口做为参数传递的时候,实际上需要的是该接口实现类的对象
public void fun(Person8 person8){
person8.study();
}
}
public class InnerClassDemo8 {
public static void main(String[] args) {
PersonDemo8 p = new PersonDemo8();
System.out.println("使用匿名内部类实现=====");
personDemo8.fun(new Person8(){
@Override
public void study() {
System.out.println("这是使用匿名内部类的方式实现");
}
});
//至此全为该方法的形参及其描述
}
}
3、例三
/*
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
通过观察main方法的实现发现,可以直接通过类名.方法的形式
说明method方法是静态的
又因为调用完method方法之后还可以调用方法,说明method方法的返回值是一个对象
又因为,后面调的方法是show()方法,通过观察发现,是接口Inter中的show()方法
所以大胆判断,method方法的返回值是接口Inter
*/
interface Inter {
public abstract void show();
}
class Outer {
// 由于返回值类型是一个接口类型,所以需要的是该接口实现类的对象
public static Inter method(){
// 在还没有学习匿名内部类之前,可以创建demo类实现该接口,再调用
// Demo9 demo = new Demo();
// return demo;
// 学习匿名内部类之后
return new Inter9(){
@Override
public void show() {
System.out.println("HelloWorld");
}
};
}
}
总结
内部类
1、内部类可以直接访问外部类的成员,包括私有
2、外部类要访问内部类的成员,必须创建对象(要在方法内创建,否则是成员变量)
1、普通内部类
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
2、静态内部类
外部类名.内部类名 对象名 = new 外部类名.内部对象
此时内部类属性的静态,通过外部类名直接调用内部类构造方法
Outer.Inner oi = new Outer.Inner();
匿名内部类
格式:
new 类名或接口名(){
重写方法;
};