接口、内部类

目录

接口

接口的本质

接口与抽象类的区别

接口中的方法都是抽象方法

接口中的变量都是静态常量

一个类可以实现多个接口

一个接口可以继承多个父接口

接口的作用

内部类

内部类概述

成员内部类(实例内部类、非静态内部类)

静态内部类

局部内部类

匿名内部类!


 

接口

 

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAaXNfa2Q=,size_20,color_FFFFFF,t_70,g_se,x_16

接口的本质

 

接口与抽象类的区别

抽象类也是类,除了可以写抽象方法以及不能直接new对象之外,其他的和普通类没有什么不一样的。接口已经另一种类型了,和类是有本质的区别的,所以不能用类的标准去衡量接口。
 
声明类的关键字是 class, 声明接口的关键字是 interface
 
抽象类是用来被继承的,java中的类是单继承。
类A继承了抽象类B,那么类A的对象就属于B类型了,可以使用多态
一个父类的引用,可以指向这个父类的任意子类对象
: 继承的关键字是 extends
接口是用来被类实现的,java中的接口可以被多实现。
类A实现接口B、C、D、E..,那么类A的对象就属于B、C、D、E等类型了,可以使用多态
一个接口的引用,可以指向这个接口的任意实现类对象
: 实现的关键字是 implements

接口中的方法都是抽象方法

public interface Action{
 
 public abstract void run();
 //默认就是public abstract修饰的
 //可以直接写成
  void test();
 

 }

接口中的变量都是静态常量

属性必须是public static fifinal修饰的静态常量。
注:可以直接使用接口名访问其属性。因为是public static修饰的
注:声明的同时就必须赋值.(因为接口中不能编写静态代码块)
public interface Action{
 public static final String NAME = "tom";//String name ="tom"
 //默认就是public static final修饰的

 int AGE = 20;
 }

main:
 System.out.println(Action.NAME);
 System.out.println(Action.AGE);

一个类可以实现多个接口

public class Student implements A,B,C,D{
 //Student需要实现接口A B C D中所有的抽象方法
 //否则Student类就要声明为抽象类,因为有抽象方法没实现
 }

main:
 A s1 = new Student();//s1只能调用接口A中声明的方法以及Object中的方法
 B s2 = new Student();//s2只能调用接口B中声明的方法以及Object中的方法
 C s3 = new Student();//s3只能调用接口C中声明的方法以及Object中的方法
 D s4 = new Student();//s4只能调用接口D中声明的方法以及Object中的方法

 

// 必要时可以类型强制转换
//接口A中有test() ,接口B中有run()
A s1 = new Student();
 s1.test();

 B s2 = new Student();
 s2.run();

 if(s1 instanceof B){
 ((B)s1).run();
 }

一个接口可以继承多个父接口

public interface A{
 public void testA();
 }

public interface B{
 public void testB();
 }
//接口C把接口A B中的方法都继承过来了
public interface C extends A,B{
 public void testC();
 }

//Student相当于实现了A B C三个接口,需要实现所有的抽象方法
 //Student的对象也就同时属于A类型 B类型 C类型
 public class Student implements C{
 public viod testA(){}
 public viod testB(){}
 public viod testC(){}
 }

main:
 C o = new Student();
 System.out.println(o instanceof A);//true
 System.out.println(o instanceof B);//true
 System.out.println(o instanceof C);//true
 System.out.println(o instanceof Student);//true
 System.out.println(o instanceof Object);//true
 System.out.println(o instanceof Teacher);//false
 //编译报错 System.out.println(o instanceof String);

System.out.println(o instanceof X);

如果o是一个接口类型声明的变量,那么只要X不是一个final修饰的类,该代码就能通过编译,至于其结果是不是true,就要看变量o指向的对象的实际类型,是不是X的子类或者实现类了。

接口的作用

接口的最主要的作用是达到统一访问,就是在创建对象的时候用接口创建
【接口名】 【对象名】= new 【实现接口的类】
 
1、Java接口中的成员变量默认都是public,static,fifinal类型的(都可省略),必须被显示初始化,即接
口中的成员变量为常量(大写,单词之间用"_"分隔)
2、Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
3、Java接口中只能包含public,static,fifinal类型的成员变量和public,abstract类型的成员方法
4、接口中没有构造方法,不能被实例化
5、一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
6、Java接口必须通过类来实现它的抽象方法
7、当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象
8、不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这
个接口的类的实例
9、 一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
interface SwimInterface{ 
void swim();
 }

class Fish{ 
int fins=4;
 }

class Duck {
 int leg=2;
 void egg(){};
 }

class Goldfish extends Fish implements SwimInterface {
 @Override public void swim() {
 System.out.println("Goldfish can swim ");
 }
 }
class SmallDuck extends Duck implements SwimInterface {
 public void egg(){
 System.out.println("SmallDuck can lay eggs ");
 }
@Override public void swim() {
 System.out.println("SmallDuck can swim ");
 }
 }

public class InterfaceDemo {
 public static void main(String[] args) {
 Goldfish goldfish=new Goldfish();
 goldfish.swim();
 SmallDuck smallDuck= new SmallDuck();
 smallDuck.swim();
 smallDuck.egg();
 }
 }

内部类

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAaXNfa2Q=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAaXNfa2Q=,size_20,color_FFFFFF,t_70,g_se,x_16

内部类概述

内部类就是在一个类的内部在定义一个类

成员内部类(实例内部类、非静态内部类)

成员内部类中不能写静态属性和方法
//【定义一个内部类】
在A类中申明了一个B类,此B类就在A的内部,并且在成员变量的位置上,所以就称为成员内部类
 public class Outer {
 private int id;

 public void out(){
 System.out.println("这是外部类方法");
 }
class Inner{
 public void in(){
 System.out.println("这是内部类方法");
 }
 }
 }
//实例化内部类,首先需要实例化外部类,通过外部类去调用内部类
public class Outer {
 private int id;
 public void out(){
 System.out.println("这是外部类方法");
 }
class Inner{
 public void in(){
 System.out.println("这是内部类方法");
 }
 }

 }

public class Test{ public static void main(String[] args) {
 //实例化成员内部类分两步
 //1、实例化外部类
 Outer outObject = new Outer();
 //2、通过外部类调用内部类
 Outer.Inner inObject = outObject.new Inner();
 //测试,调用内部类中的方法
inObject.in();
//打印:这是内部类方法
 }
 }

 

 

//1. 访问外部类的所有属性(这里的属性包括私有的成员变量,方法)
public class Outer {
 private int id;
 public void out(){
 System.out.println("这是外部类方法");
 }
class Inner{
 public void in(){
 System.out.println("这是内部类方法");
 }
//内部类访问外部类私有的成员变量
 public void useId(){
 System.out.println(id+3);
 }
//内部类访问外部类的方法
 public void useOut(){
 out();
 }
 }
 }
public class Test{
 public static void main(String[] args) {
 //实例化成员内部类分两步
 //1、实例化外部类
 Outer outObject = new Outer();
 //2、通过外部类调用内部类
 Outer.Inner inObject = outObject.new Inner();
 //测试
 inObject.useId();//打印3,因为id初始化值为0,0+3就为3,其中在内部类就使用了 外部类的私有成员变量id。
 inObject.useOut();//打印:这是外部类方法
 }
 }
//如果内部类中的变量名和外部类的成员变量名一样,要通过创建外部类对象 "."属性来访问外部类
属性,通过this.属性访问内部类成员属性
public class Outer {
 private int id;//默认初始化0
 public void out(){
 System.out.println("这是外部类方法");
 }
class Inner{
 private int id=8; //这个id跟外部类的属性id名称一样。
 public void in(){
 System.out.println("这是内部类方法");
 }
public void test(){
 System.out.println(id);//输出8,内部类中的变量会暂时将外部类的成员变量给隐藏
 //如何调用外部类的成员变量呢?通过Outer.this,想要知道为什么能通过这个来调用,就得明白下面这个原理
//想实例化内部类对象,就必须通过外部类对象,当外部类对象来new出内部类对象时,会
//把自己(外部类对象)的引用传到了内部类中,所以内部类就可以通过 Outer.this来访问外部类的属性和方法,到这里,你也就可以知道为什么内部类可以访问外部类的属性和方法,这里由于有两个相同的属性名称,所以需要显示的用Outer.this来调用外部类的属性,平常如果属性名不重复,那么我们在内部类中调用外部类的属性和方法时,前面就隐式的调用了Outer.this。
 System.out.println(Outer.this.id);//输出外部类的属性id。也就是输出0
 }
 }
 }

 

静态内部类

1)static修饰成员变量:整个类的实例共享静态变量
2)static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修饰的方法或属性
3)被static修饰了的成员变量和方法能直接被类名调用。
4)static不能修饰局部变量,切记,不要搞混淆了,static平常就用来修饰成员变量和方法。
public class StaticInnerClassTest {
 private String name;
 private static int age;
 public void run(){}
 public static void go(){}
 //外部类访问静态内部类
 public void test(){
 StaticInnerClass sic = new StaticInnerClass(); //静态的内部类不需要依赖外部类,所以不用this
 sic.name = "tom";
sic.test1("jack");
 StaticInnerClass.age=10;
 StaticInnerClass.test2("xixi");
 }
private static class StaticInnerClass{
 private String name;
 private static int age;
 public void test1(String name){
 System.out.println(name);
 System.out.println(this.name);
 System.out.println(StaticInnerClass.age);
 
 System.out.println(StaticInnerClassTest.age); //System.out.println(StaticInnerClassTest.this.name);静态类不能访问非静态属性 

  StaticInnerClassTest.go();
 //StaticInnerClassTest.this.run();静态类不能访问非静态方法
 }
public static void test2(String name){
 //只能访问自己和外部类的静态属性和方法
 System.out.println(name);
 //System.out.println(this.name);静态方法里面连自己类的非静态属性都不能访问 
  System.out.println(StaticInnerClass.age);
 System.out.println(StaticInnerClassTest.age); //System.out.println(StaticInnerClassTest.this.name);静态方法不能 访问非静态属性 StaticInnerClassTest.go();
 //StaticInnerClassTest.this.run();静态方法不能访问非静态方法
 }
 }
 }
1、我们上面说的内部类能够调用外部类的方法和属性,在静态内部类中就行了,因为静态内部类没有了指向外部类对象的引用。除非外部类中的方法或者属性也是静态的。这就回归到了static关键字的用法。
2、静态内部类能够直接被外部类给实例化,不需要使用外部类对象
Outer.Inner inner = new Outer.Inner();
3、静态内部类中可以声明静态方法和静态变量,但是非静态内部类中就不可以声明静态方法和静态变量.

局部内部类

局部内部类是在一个方法内部声明的一个类
局部内部类中可以访问外部类的成员变量及方法
局部内部类中如果要访问该内部类所在方法中的局部变量,那么这个局部变量就必须是final修饰的
public class Outer {
 private int id;
 //在method01方法中有一个Inner内部类,这个内部类就称为局部内部类
 public void method01(){
class Inner{ 
public void in(){
 System.out.println("这是局部内部类");
 }
 }
 }
 }
1. 在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰
public class Outer {
 private int id;
 public void method01(){
 final int cid = 3; //这个就是局部变量cid。要让局部内部类使用,就得变为final并且赋值,如果不使用final修饰,就会报错
 class Inner{
 //内部类的第一个方法
 public void in(){ 
System.out.println("这是局部内部类");
 }
//内部类中的使用局部变量cid的方法
 public void useCid(){
 System.out.println(cid);
 }
 } } }
1. 局部内部类不能通过外部类对象直接实例化,而是在方法中实例化出自己来,然后通过内部类对象调用自己类中的方法。
public class Outer {
 private int id;
 public void out(){
 System.out.println("外部类方法");
 }
public void method01(){
 class Inner{ public void in(){
System.out.println("这是局部内部类");
 }
 }
 //关键在这里,如需要在method01方法中自己创建内部类实例,然后调用内部类中的方法,等待外部类调用method01方法,就可以执行到内部类中的方法了。
 Inner In = new Inner();
 In.in(); } }
使用局部内部类需要注意的地方就刚才上面说的:
1、在局部内部类中,如果要访问局部变量,那么该局部变量要用fifinal修饰
2、如何调用局部内部类方法。
public class LocalInnerClassTest {
 private String name;
 private static int age;
 public void run(){}
 public static void go(){} 
//局部内部类要定义在方法中
 public void test(){
 final String myname="";
 class LocalInnerClass{
 private String name; // private static int age;不能定义静态属性
 public void test(String name){
 System.out.println(name);
 System.out.println(this.name);
 System.out.println(myname);
 System.out.println(LocalInnerClassTest.this.name);
 LocalInnerClassTest.this.run();
 LocalInnerClassTest.go();
 }
 }
//局部内部类只能在自己的方法中用,因为局部内部类相当于一个局部变量,除了方法就找不到了。 
LocalInnerClass lic = new LocalInnerClass();
 lic.name="tom";
 lic.test("test");
 } }

匿名内部类!

如果一个对象只要使用一次,那么我们就是需要new Object().method()。 就可以了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。
public class Test {
 public static void main(String[] args) {
 //讲new出来的Apple实例赋给apple变量保存起来,但是我们只需要用一次,就可以这样写
 Apple apple = new Apple();
 apple.eat(); //这种就叫做匿名对象的使用,不把实例保存到变量中。
 new Apple().eat();
 }
 }
class Apple{
 public void eat(){
 System.out.println("我要被吃了"); } }
匿名对象:我只需要用一次,那么我就不用声明一个该类型变量来保存对象了,
匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。不然先写出一个内部类的全部实现来,然后就调用它一次,岂不是用完之后就一直将其放在那,那就没必要那样。
1. 匿名内部类需要依托于其他类或者接口来创建
  • 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
  • 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
2. 匿名内部类的声明必须是在使用new关键字的时候
  • 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
//A是一个类(普通类、抽象类都可以),依托于A类创建一个匿名内部类对象
main: A a = new A(){
 //实现A中的抽象方法
 //或者重写A中的普通方法
 };
//注:这个大括号里面其实就是这个内部类的代码,只不过是声明该内部类的同时就是要new创建了其对象, 并且不能反复使用,因为没有名字。
// 例如: B是一个接口,依托于B接口创建一个匿名内部类对象
 B b = new B(){ //实现B中的抽象方法 };
1. 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。
2. 匿名内部中,我们不能写出其构造器,因为没有名字。
3. 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)
public interface Work{
 void doWork();
 }
public class AnonymousOutterClass{
 private String name;
 private static int age;
 public void say(){}
 public static void go(){}
 public void test(){
 final int i = 90;
 Work w = new Work(){ 
public void doWork(){
 System.out.println(AnonymousOutterClass.this.name); System.out.println(AnonymousOutterClass.age);
 AnonymousOutterClass.this.say();
 AnonymousOutterClass.go();
 System.out.println(i);
 }
 };
w.doWork(); } }
//【不用匿名内部类】
public class Test {
 public static void main(String[] args) {
 //如果我们需要使用接口中的方法,我们就需要走3步,1、实现接口 2、创建实现接口类的实 例对象 3、通过对象调用方法 
//第二步
 Test02 test = new Test02();
 //第三步
 test.method();
 } 
}
//接口Test1
 interface Test01{ public void method(); }
//第一步、实现Test01接口
 class Test02 implements Test01{
 @Override public void method() {
 System.out.println("实现了Test接口的方法"); } }
//【使用匿名内部类】
public class Test {
public static void main(String[] args) {
 //如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其类的对象创建出来。 
new Test1(){
 public void method(){
 System.out.println("实现了Test接口的方法");
 }
 }.method();
 }
 }
interface Test1{ 
public void method(); }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
成员内部类是存在于某个类的内部,与全局属性或者方法同级的内部类。它可以直接调用外部类的所有方法,包括静态方法和非静态方法。一个例子是在Person类中定义了一个成员内部类DoWork,它实现了接口Work。\[1\] 静态内部类是定义在外部类内部的静态类。它可以直接访问外部类的非静态成员。静态内部类与外部类之间没有直接的关联,可以通过外部类名来访问静态内部类。\[2\] 接口内部类是定义在接口内部的类。它可以被实现该接口的类所使用。接口内部类的特点是没有构造器,它在编译时会自动起名为xxx$1.class。\[3\] 局部内部类是定义在方法内部的类。它只能在方法内部使用,并且只有在方法的局部变量被标记为final或者是effectively final的情况下,内部类才能使用这些局部变量。\[2\] 匿名内部类是一种没有构造器的类,它通常用于接口返回。匿名内部类不能存在任何静态的变量或方法,它是局部内部类的特例。在编译时,编译器会自动为匿名内部类起一个名字,例如xxx$1.class。\[3\] #### 引用[.reference_title] - *1* *2* *3* [什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的区别及作用?](https://blog.csdn.net/sulixu/article/details/120028541)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值