内部类

1、成员内部类

  1. 调用成员内部类

    //在外面的类的最后,写一个方法,调用成员内部类(创建对象,在访问)
    class Outer08{
    class Inner08{ //成员内部类
    public void say(){ }
    } public void t1(){
    Inner08 inner08 = new Inner08();
    inner08.say();
    }
    }
  2. 可以直接访问外部类的所有成员,包含私有的。

  3. 外部其他类调用内部类的二种方法

    //
    Outero8.Inner08 inner08 = outero8.new Inner08();
    inner08.say();
    //2. 在外部类中,编写一个方法,可以返回 Inner08 对象
    //方法,返回一个Inner08实例
    public Inner08 getInner08Instance(){
    return new Inner08();
    }
    //调用
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
    inner08Instance.say();
  4. 如果成员内部类的成员和外部类的成员重名,会遵守就近原则,可以通过 外部类.this.属性 来访问。

2、静态内部类

public class StaticInnerClass01 {
public static void main(String[] args) { Outer10 outer10 = new Outer10();
outer10.m1();
//外部其他类 使用静态内部类
//方式1
//直接创建一个 外部类.静态内部类 对象
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();
//方式2
//编写一个方法,可以返回静态内部类的对象实例
Outer10.Inner10 inner101 = outer10.getInner10(); Outer10.Inner10 inner10_ = Outer10.getInner10_();
inner10_.say();
}
} class Outer10 {//外部类
private int n1 = 10;
private static String name = "张三";
private static void cry() {}
//Inner10就是静态内部类
//1. 放在外部类的成员位置
//2. 使用static修饰
//3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
//4. 可以添加任意访问修饰符(public, protected,默认,private),因为它的地位就是一个成员
//5. 作用域:同其他的成员,为整个类体
//6. 如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则,
// 如果想访问外部类的成员,则可以使用(外部类名.成员)
static class Inner10 {
private static String name = "李四";
public void say() {
System.out.println(name + " 外部类name= " + Outer10.name);
cry();
}
}
//外部类访问静态内部类,创建对象,在访问
public void m1() {
Inner10 inner10 = new Inner10();
inner10.say();
} public Inner10 getInner10() {
return new Inner10();
} public static Inner10 getInner10_() {
return new Inner10();
}
} /* 运行结果
李四 外部类name= 张三
李四 外部类name= 张三
李四 外部类name= 张三
*/

3、局部内部类

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,但是可以使用 final 修饰

  3. 作用域:仅仅在定义它的方法或代码块中

  4. 外部类在方法中,可以创建 Inner02 对象,然后调用方法即可

    class Outer02{//外部类
    public void m1(){//方法
    final class Inner02{//局部内部类(本质仍然是一个类)
    public void f1(){ }
    }
    Inner02 inner02 = new Inner02();
    inner02.fi();
    }
    } //main 方法中调用
    Outer02 outer02 = new Outer02();
    outer02.m1(); //调用了fi() 方法
  5. (在类的方法中的类,调用的时候可以在此方法最后 new 局部内部类)

  6. 如果外部类和局部内部类的成员重名,默认遵循就近原则,可以通过 外部类.this.成员 来访问。

4、匿名内部类

  1. 匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

  2. 匿名内部类的基本语法

    ​ new 类或接口(参数列表){

    ​ 类体

    ​ };

  3. 本质还是一个类,内部类,该类没有名字,同时还是一个对象

  4. 可以直接访问外部类的所有成员,包含私有的

  5. 不能添加访问修饰符,因为它的地位就是一个局部变量

  6. 作用域:仅仅在定义它的方法或代码快中

  7. 匿名内部类访问外部类成员,直接访问

  8. 外部其他类不能访问匿名内部类(因为匿名内部类地位是一个局部变量)

  9. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,

    如果想访问外部类成员,则可以使用 (外部类名.this.成员) 去访问

public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
} class Outer04 { //外部类
private int n1 = 10;
public void method() {
//基于接口的匿名内部类
//3. 需求是 Tiger/Dog 类只是使用一次,后面再不使用
//4. 可以使用匿名内部类来简化开发
//5. tiger的编译类型 A
//6. tiger的运行类型 就是匿名内部类 XXXX => Outer04$1
/*
我们看底层
class XXXX implements A {
@Override
public void cry() {
System.out.println("老虎来了。。。");
}
}
*/
//7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址
// 返回给 tiger
//8. 匿名内部类使用一次,就不能使用了,但是tiger可以多次使用
A tiger = new A() {
@Override
public void cry() {
System.out.println("老虎来了。。。");
}
};
System.out.println("tiger的运行类型=" + tiger.getClass());
tiger.cry();
tiger.cry();
tiger.cry(); //演示基于类的匿名内部类
//1. father编译类型 Father
//2. father运行类型 Outer04$2
//3. 底层会创建匿名内部类
/*
class Outer04$2 extends Father{
}
*/
//4. 同时也返回了 匿名内部类 Outer04$2 的对象
//5. 注意("jack")参数列表会传递给 构造器
Father father = new Father("jack") {
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father的运行类型=" + father.getClass());
father.test(); //基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头。。。");
}
};
animal.eat(); }
} interface A { //接口
public void cry();
} class Father {
public Father(String name) { //构造器
System.out.println("接收到的name= " + name);
}
public void test() { }
} abstract class Animal { //抽象类
abstract void eat();
} /*
运行结果
tiger的运行类型=class com.hspedu.practice.Outer04$1
老虎来了。。。
老虎来了。。。
老虎来了。。。
接收到的name= jack
father的运行类型=class com.hspedu.practice.Outer04$2
匿名内部类重写了test方法
小狗吃骨头。。。
*/
public class AnonymousInnerClassDetail {
public static void main(String[] args) {
Outer05 outer05 = new Outer05();
outer05.f1();
System.out.println("main outer05 hashcode=" + outer05); }
} class Outer05 {
private int n1 = 99;
public void f1(){
//创建一个基于基本类的匿名内部类
Person01 p = new Person01(){
private int n1 = 88;
@Override
public void hi() {
System.out.println("匿名内部类重写了 hi()方法 n1 = " + n1 +
"外部类的n1=" + Outer05.this.n1);
//Outer05.this 就是调用 f1的 对象
System.out.println("Outer05.this hashcode=" + Outer05.this);
}
};
p.hi(); //动态绑定,运行类型是 Outer05$1 //也可以直接调用,匿名内部类本身也是返回对象
// class 匿名内部类 extends Person {}
new Person01(){
@Override
public void hi() {
System.out.println("匿名内部类重写了 hi()方法,哈哈哈。。。");
} @Override
public void ok(String str) {
super.ok(str);
}
}.ok("jack");
}
} class Person01 {
public void hi() {
System.out.println("Person01 hi()");
} public void ok(String str) {
System.out.println("Person01 ok()" + str);
}
} /*
运行结果
匿名内部类重写了 hi()方法 n1 = 88外部类的n1=99
Outer05.this hashcode=com.hspedu.practice.Outer05@154617c
Person01 ok()jack
main outer05 hashcode=com.hspedu.practice.Outer05@154617c
*/
public class InnerClassExercise01 {
public static void main(String[] args) { //当作实参直接传递,简洁高效
f1(new IL() {
@Override
public void show() {
System.out.println("这是一副名画。。。");
}
}); //传统方法
f1(new Picture()); }
//静态方法 形参是接口类型
public static void f1(IL il) {
il.show();
}
} interface IL {
void show();
} class Picture implements IL {
@Override
public void show() {
System.out.println("这是一副名画。。。");
}
} /*
运行结果
这是一副名画。。。
这是一副名画。。。
*/
public class InnerClassExercise02 {
public static void main(String[] args) {
CellPhone cellPhone = new CellPhone();
//1. 传递的是实现了 Bell接口的匿名内部类
//2. 重写了 ring
//3. Bell bell = new Bell() {
// @Override
// public void ring() {
// System.out.println("懒猪起床了。");
// }
// }
cellPhone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了。");
}
}); cellPhone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴们上课了。");
}
});
}
} interface Bell{
void ring();
} class CellPhone{
public void alarmClock(Bell bell){
System.out.println(bell.getClass());
bell.ring();
}
} /*
运行结果
class com.hspedu.practice.InnerClassExercise02$1
懒猪起床了。
class com.hspedu.practice.InnerClassExercise02$2
小伙伴们上课了。
*/

Java SE 四大内部类的更多相关文章

  1. 学习android学习必备的java基础知识--四大内部类

    学习android必备的java基础知识--四大内部类 今天学习android课程,因为我的主专业是JAVA,但是兴趣班却有这其他专业的同学,学习android 需要具备一些java的基础知识,因此就 ...

  2. Java Se 基础系列(笔记) -- OO

    记录所学到的关于Java Se的一些基础知识 1.对象是通过“属性(成员变量)”和“方法”来分别对应事物所具有的静态属性和动态属性 2.类(Class)是对某一类事物的抽象,对象(Object)为某个 ...

  3. 黑马程序员 ——Java SE(1)

    ----<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训 ...

  4. Java IO 四大附加接口、try-with-resource

    Java IO 四大附加接口.try-with-resource @author ixenos 四大附加接口 Closeable.Flushable.Readable.Appendable Close ...

  5. Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)

    声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...

  6. Java SE教程

    第0讲 开山篇 读前介绍:本文中如下文本格式是超链接,可以点击跳转 >>超链接<< 我的学习目标:基础要坚如磐石   代码要十份规范   笔记要认真详实 一.java内容介绍 ...

  7. Java SE 开篇

    一.  Java SE 开篇 1.  Java 基本数据类型及其对应的包装类 基本数据类型 对应的包装类 * byte Byte * boolean Boolean * char Character ...

  8. Java中的内部类怎么用

    一.为什么需要内部类?java内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时 ...

  9. Java SE(1)

    Java SE基础回顾 1.循环语句中的break是终止全部循环,跳出循环体:而continue是终止本次循环,跳执行下一循环 2.return语句有两个作用:返回值:结束方法的运行 3.对于java ...

随机推荐

  1. Python实现哈希表(分离链接法)

    一.python实现哈希表 只使用list,构建简单的哈希表(字典对象) # 不使用字典构造的分离连接法版哈希表 class HashList(): """ Simple ...

  2. Linux操作系统(7):rpm包管理和yum软件包在线管理

    一.rpm 包的管理 介绍:一种用于互联网下载包的打包及安装工具,它包含在某些 Linux 分发版中.它生成具有.RPM 扩展名的文件.RPM 是 RedHat Package Manager(Red ...

  3. zookeeper和spring cloud版本冲突

    1.使用elastic-job进行任务调度,而核心的就是使用zookeeper进行管理,但这个与spring cloud 冲突造成启动不了 |ERROR |main |SpringApplicatio ...

  4. java 配置aop 写入无效

    一个项目不同的Module 含有相同的路径以及文件,配置的AOP的expression吸入日志无效,要点击包查看当前包是否是本Module下面的,不然调用无效. 改为本Module就行了

  5. APISpace 日出日落API接口 免费好用

    日出是每个早晨太阳的一半从地平线探出头的时刻,也指太阳穿过地平线的整个过程及其伴随的大气效应.日落是指由于地球自转导致太阳每天从地平线消失的时刻.从赤道上看,春分和秋分时,太阳从正西方落下.从中纬度地 ...

  6. 5-21 拦截器 Interceptor

    Spring MVC拦截器 什么是拦截器 拦截器是SpringMvc框架提供的功能 它可以在控制器方法运行之前或运行之后(还有其它特殊时机)对请求进行处理或加工的特定接口 常见面试题:过滤器和拦截器的 ...

  7. 获取字典中values值中最大的数,返回对应的keys

    1.字典中键值对的获取 print(data.values()) # 查看字典的值 print(data.keys()) # 查看字典的key 2.对字典中的值进行排序 sorted(data.val ...

  8. 20220722-Java可变参数

    Java可变参数总结 来源:B站韩顺平老师的Java入门教学 代码示例如下: public void f(String str,int... nums){ 方法体; } 代码示例如下: public ...

  9. 从零开始Blazor Server(3)--添加cookie授权

    认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...

  10. Java异步记录日志-2022新项目

    一.业务场景 web项目开发中,经常会有的一个操作是记录请求日志,比如记录请求的IP地址,记录请求的路径,记录请求的参数等等. 每个系统都会根据自己的需要来记录一些请求相关的日志.一般会将记录的日志信 ...