内部类(累不累)
class Outer{//外部类
private String name;//属性
public void hi(){
System.out.println("hi");//方法
}
public Outer(String name) {//构造器
this.name = name;
}
{
//代码块
}
//内部类
class inner{
}
}
内部类的分类
定义在外部类的局部位置上(方法中) | 定义在外部类的成员位置上 |
---|---|
局部内部类(有类名) | 成员内部类(没有static修饰) |
匿名内部类(没有类名【重点】) | 静态内部类(使用static修饰) |
局部内部类
package com.LJX.InnerClass;
/*
* 演示局部内部类的使用
* */
public class localInnerclass {//外部其他类
//不能访问 --- > 局部内部类
public static void main(String[] args) {
outer02 outer = new outer02();
outer.m1();
}
}
class outer02{//外部类
private int n1 = 200;
public void m1(){//方法
//1.局部内部类定义在外部类的局部位置,通常在方法
//3.不能添加访问修饰符,但可以使用final修饰
//4.作用域:仅仅在定义他的方法或代码块中
class Inner{//局部内部类(仍然是一个类)
//2.额可以直接访问外部类的所有成员,包括私有
private int n1 = 900;
public void fi(){
//5.局部内部类可以直接访问外部的成员,比如下面的n1
//7.如果外部类与内部类重名时,遵守就近原则
//使用 外部类的成员,用外部类名.this.成员
//outer02.this.n1本质是外部类的对象
//那个对象调用m1(),outer02.this.n1就是那个对象
/*
* 在Java中,内部类实例通常会隐式地持有一个对外部类实例的引用
* 这是由编译器在生成字节码时自动完成的。
* 当内部类需要引用外部类的实例时,编译器会在内部类的构造函数中添加一个对外部类实例的引用。
* 这个引用的类型是外部类的类型,因此可以通过外部类名.this来显式地获取对外部类实例的引用。
* */
System.out.println("n1 = " + n1 + "外部类的n1= " + outer02.this.n1);
}
}
//6.外部类访问内部类的成员,
// 外部类在方法中,可以定义Inner对象,然后调用方法
Inner inner = new Inner();
inner.fi();
}
}
匿名内部类
在Java中,匿名内部类是一种没有名称的内部类。它通常用于创建一个只需要使用一次的类的实例,并且通常作为参数传递给方法或作为接口的实现。匿名内部类通常在创建对象的同时定义类的实现,可以直接在代码中使用,而不需要单独定义一个类。它的语法形式为:new 父类或接口名() { // 匿名内部类的实现 }。使用匿名内部类可以简化代码,提高代码的可读性和可维护性。
本质
package com.LJX.InnerClass;
import com.LJX.Static_.Father;
/*
演示匿名内部类的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
new Outer01().methods();
}
}
class Outer01{//外部类
private int n1 = 100;//属性
public void methods(){
//基于接口的匿名内部类
//老韩解读:
//1.需求:想使用IA接口,并创建对象
//2.传统方式:是写一个类,并实现接口,并创建对象
//3.老韩需求:tiger/dog 类只是使用一次,后面不再使用
//4.可以使用匿名内部类来简化开发
//5. tiger 的编译类型 ? IA
//6. tiger 的运行类型 ? 就是我们的匿名内部类
/*
我们的系统底层会自动 分配类名 Outer01$1
class Outer01$1 implement IA{
@Override
public void cry() {
System.out.println("老虎汪汪叫....");
}
};
*/
//7.jdk底层在创建匿名内部类,outer01$1,立即创建了他的实例,并把他的地址返回
//8.匿名内部类使用一次后,就不能再使用
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎汪汪叫....");
}
};
// IA tiger = new tiger();
// tiger.cry();
}
}
interface IA{//接口
public void cry();
}
//class tiger implements IA{
//
// @Override
// public void cry() {
// System.out.println("老虎汪汪叫....");
// }
//}
//class DOg implements IA{
// @Override
// public void cry() {
// System.out.println("小狗汪汪叫....");
// }
//}
class father{
public father(String name){//构造器
}
public void test(){
}
}
package com.LJX.InnerClass;
public class A {
public static void main(String[] args) {
new Outer01().methods();
}
}
class Outer01 {//外部类
private int n1 = 100;//属性
//基于类的匿名内部类
//分析
//1.p1的编译类型?father
//2.p1的运行类型?outer01$1
//底层会创建匿名内部类
/*
public void methods(){
class outer01$2 extends father{
public void test() { System.out.println("重写的test方法..."); }
};
System.out.println("p1对象的运行类型 = "+ p1.getClass());
}
*/
//4.返回的是匿名内部类Outer$1对象的地址
//5.jack的值会传给构造器
public void methods() {
father p1 = new father("Jack") {
//重写test方法
@Override
public void test() {
System.out.println("重写的test方法...");
}
};
System.out.println("p1对象的运行类型 = " + p1.getClass());
p1.test();
//基于抽象类的匿名内部类
Animal p2 = new Animal() {
//Class 'Anonymous class derived from Animal' must implement abstract method 'makesound()' in 'Animal'
@Override
public void makesound() {
System.out.println("动物在叫...");
}
};
}
}
class father{
public father(String name){//构造器
}
public void test(){
}
}
abstract class Animal{//抽象类
public abstract void makesound();
}
细节
package com.LJX.InnerClass;
public class Detail01 {
public static void main(String[] args) {
new Outer02().f1();
}
}
class Outer02{
private int n1 = 100;
public void f1() {
//创建一个基于子类的匿名内部类
//调用方式1
// new person(){
// @Override
// public void hi() {
// System.out.println("匿名内部类的重写 hi()");
// }
// }.hi();
//第二种
person p = new person(){
//3.可以使用外部类的所有成员
//4.不能添加访问修饰符,因为他的地位就是局部变量
//5.作用域:仅仅在定义他的方法或代码块中
//6.外部其他类不能访问匿名内部类
//7.当外部类与内部类重名时,内部类访问遵循就近原则
//外部类.this.成员名 来访问外部类成员
@Override
public void hi() {
System.out.println("匿名内部类的重写 hi()");
}
};
p.hi();
}
}
class person{
public void hi(){
System.out.println("person hi()");
}
}
使用
当作实参直接传递,简洁高效
package com.LJX.InnerClass;
public class AnonymousUse {
public static void main(String[] args) {
// new Outer03().f1(new car());
Outer03.f1(new IA() {
@Override
public void show() {
System.out.println("boom boom bbom");
}
});
}
}
class Outer03{
private int n1 = 100;
//传统方法,偏--->硬编码
// public void f1(IA ia){
// ia.show();
// }
//当我们这个类只需调用一次,考虑使用匿名内部类
//静态方法,形参是接口类型
public static void f1(IA ia){
ia.show();
}
}
interface IA{
public void show() ;
}
//class car implements IA{
// @Override
// public void show() {
// System.out.println("boom boom boom ...");
// }
//}
成员内部类
package com.LJX.InnerClass;
//演示成员内部类的使用
public class NumberInnerClass {
public static void main(String[] args) {
Outer04 p = new Outer04();
p.f1();
//外部其他类使用我们的成员内部类,三种方式、
//1.Outer04.new inner01; 相当于把 new inner01()当作是Outer的成员
//p 是外部类的实例
Outer04.inner01 p1 = p.new inner01();
//2.在外部类中定义一个方法,返回inner01
Outer04.inner01 p3 = p.getInner01();
p3.say();
}
}
//7.如果外部类与内部类重名时,遵守就近原则
//使用 外部类的成员,用外部类名.this.成员
//outer04.this.n1本质是外部类的对象
class Outer04{
private int age = 100;
public String name = "光头强";
//可以添加修饰符
public class inner01{//成员内部类
public void say(){
//直接访问外部类的所有成员
System.out.println("name = " + name + "年龄" + age);
}
}
//使用成员内部类
public void f1(){
//外部类 使用 成员内部类
//创建成员内部类的实例,然后使用
inner01 inter01 = new inner01();
inter01.say();
}
public inner01 getInner01(){
inner01 inner01 = new inner01();
return inner01;
}
}
静态内部类
package com.LJX.InnerClass;
public class StaticInnerClass {
public static void main(String[] args) {
//外部其他类访问------>静态内部类
//方式1
//因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer05.inner02 p = new Outer05.inner02();
p.say();
//方式2
//编写方法,返回inner02对象
Outer05.inner02 m2 = Outer05.m2();
m2.say();
}
}
class Outer05{
private int n1 = 100;
private static String name = "fuck";
//inner02是静态内部类
//使用static修饰
//可以添加任意的修饰符
//作用域:整个整体
public static class inner02{
public void say(){
//1.可以访问所有静态成员,不能访问非静态
// System.out.println(n1);
String name = "大维";
System.out.println(name);
System.out.println("-------------------");
//当外部类与静态内部类重名,就近原则
//访问外部类,外部类名.成员
System.out.println("外部类的name = " + Outer05.name);
}
}
//外部类访问 ---> 静态内部类
//先创建对象
public void showName(){
inner02 inner02 = new inner02();
inner02.say();
}
public inner02 m1(){
return new inner02();
}
public static inner02 m2(){
return new inner02();
}
}