Day37--N种内部类
内部类
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
示例:
创建外部类Outer,并设置属性private int id;方法public void out System.out.println("这是外部类的方法");
设置内部类Inner,内部类的方法in,输出“这是内部类的方法”
package com.liu.oop.demo10;
//Outer 外部类
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
//Inner 这是内部类的方法
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
}
}
如何在Application里面创建内部类的对象、使用内部类的方法?
package com.liu.oop;
import com.liu.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
//创建内部类的对象
//1. 创建外部类的对象
Outer outer = new Outer();
//2.通过外部类来实例化内部类
//outer.new Inner();
Outer.Inner inner = outer.new Inner();
//使用内部类的方法
inner.in();//这是内部类的方法
}
}
内部类有哪些作用?
内部非静态类可以访问外部类的属性(包括私有属性)。
package com.liu.oop.demo10;
//Outer 外部类
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
//Inner 这是内部类的方法
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得内部类的私有属性
public void getId(){
System.out.println(id);
}
}
}
package com.liu.oop;
import com.liu.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
//创建内部类的对象
//1. 创建外部类的对象
Outer outer = new Outer();
//2.通过外部类来实例化内部类
//outer.new Inner();
Outer.Inner inner = outer.new Inner();
//使用内部类的方法
inner.getId();//10
}
}
内部类可以访问外部类的私有方法
package com.liu.oop.demo10;
//Outer 外部类
public class Outer {
private int id=10;
public void out1(){
System.out.println("这是外部类的方法1");
}
private void out2(){
System.out.println("这是外部类的方法2");
}
//Inner 这是内部类的方法
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得内部类的私有属性
public void getId(){
System.out.println(id);
}
//获得内部类的私有方法
public void getOut2(){
Outer.this.out2();
}
}
}
详细解释:
Outer.this
的含义- 当在内部类中使用
Outer.this
时,Outer.this
指的是外部类(Outer
类)的当前实例。 - 例如,在
Inner
类的callOuterOut2
方法中:
- 当在内部类中使用
public void getOut2() {
Outer.this.out2();
}
Outer.this
表示获取外部类Outer
的当前实例。然后通过这个实例来调用外部类的out2
方法。如果没有Outer.this
,编译器可能会混淆,不知道你要调用的是哪个out2
方法(因为内部类可能也有自己的方法,或者存在名称冲突的情况)。
比如:
- 当内部类和外部类有同名的成员变量或方法时,使用
Outer.this
可以明确地访问外部类的成员。 - 例如,如果
Inner
类也有一个名为id
的变量,而你想访问外部类Outer
的id
变量,你可以这样写:
public class Inner{
private int id = 20;
public void printIds() {
System.out.println("Inner id: " + this.id);
System.out.println("Outer id: " + Outer.this.id);
}
}
- 这里
this.id
访问的是内部类Inner
的id
变量,而Outer.this.id
访问的是外部类Outer
的id
变量。
总之,Outer.this
是在内部类中访问外部类当前实例的一种方式,用于明确地调用外部类的成员。
与上面相反,内部静态类不能直接调用外部类的非静态属性。
例如:将内部类属性改为static,立刻报错
package com.liu.oop.demo10;
//Outer 外部类
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法1");
}
//Inner 这是内部类的方法
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得内部类的私有属性
public void getId(){
System.out.println(id);//报错
}
}
}
一个Java文件只能有一个public class文件(非内部类),但是可以有多个class文件
package com.liu.oop.demo10;
public class Outer {
}
class A{
}
此时,在项目列表里面,就可以看到
局部内部类:类可以写在方法里面
package com.liu.oop.demo10;
public class Outer {
public void method(){
class A{
}
}
}
没有名字初始化类,不用将类保存到变量中
package com.liu.oop.demo10;
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将类保存到变量中
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
匿名内部类:
package com.liu.oop.demo10;
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将类保存到变量中
new Apple().eat();
UserService userService=new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}
对代码的解释:
-
在
UserService userService = new UserService() {... };
这行代码中:
- 创建接口的实例:虽然接口本身不能被实例化(因为它没有构造函数且只定义了方法规范),但在这里通过使用匿名内部类的方式,实际上是在创建一个实现了
UserService
接口的匿名类的实例。 - 实现接口方法:紧跟在
new UserService()
后面的大括号内的代码{ @Override public void hello() { } }
就是在实现UserService
接口中的hello
方法。这里虽然方法体暂时为空,但按照要求必须提供hello
方法的具体实现,因为要创建的是UserService
接口的一个有效实现类的实例。 - 赋值给变量:最后将创建的这个实现了
UserService
接口的匿名类的实例赋值给变量userService
,这样就可以在后续的代码中通过这个变量来调用该匿名类实现的方法(在这里就是hello
方法)。
- 创建接口的实例:虽然接口本身不能被实例化(因为它没有构造函数且只定义了方法规范),但在这里通过使用匿名内部类的方式,实际上是在创建一个实现了
接口不能初始化,但可以通过实现接口的类来使用接口。例如,创建一个实现Animal
接口的Cat
类:
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("喵喵!");
}
}
-
然后可以在其他代码中使用这些实现类:
public class Main { public static void main(String[] args) { Animal cat = new Cat(); cat.makeSound(); } }
- 在这里,
Animal
接口本身没有被初始化,而是通过Cat
类(Animal
接口的实现类)的实例化来使用接口中定义的方法。
- 在这里,