第四章、Java面向对象(八)

第四章、Java面向对象(八)

本人也是刚入门Java语言,可能会有一些地方出现错误,描述的不对。如果发现不对的地方请及时指出,好对其进行修改。这样不仅可以让我学到东西,也可以让其他刚入门的朋友学习更正确的内容。

所有内容仅供参考。不具有完全的准确性!

注:关于Java的所有内容都会参考到尚硅谷在网上公开的学习视频及其提供的PPT

一、接口的使用
interface: 接口
接口和类是并列的两个结构
推荐:https://blog.csdn.net/qq_19782019/article/details/80259836
(一)为什么要有接口
通过继承我们了解到,一个类最多只能继承一个父类,这一点在我们写代码时是有很大限制的。有时多个类中的属性和方法都是我们想要的,但又由于只能继承一个类,我们就需要再把其他没能继承的类中的属性和方法重新再写一遍。
这时接口就出现了,接口说我可以实现多继承(严格来说不叫继承,而是可以实现多个类)。通过接口我们就可以很好的接口上述情况。

例String类:
implements 后边都是实现的接口,接口和接口之间逗号隔开

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {
               .....
               }

(二)什么是接口

  • 官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

  • 我的解释:接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成(抽象方法和常量值定义的集合)。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法。(JDK1.7及之前)

  • 接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。

(三)如何使用接口
定义Java类的语法格式:先写extends,后写implements
例:

public class C extends A implements B{....}

语法格式:

public interface A{
...
}

将class替换为interface,public可以省略

  • JDK 7 及 以前: 只能够定义全局常量和抽象方法
    全局常量:public static final.(可以省略不写,仍是常量)
    抽象方法:public abstract
  • JDK 8: 除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
  • 接口中不可以定义构造器:意味着接口不可以实例化
  • 类需要通过implements的方式实现接口
    如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
    如果实现类没有全部重写接口中的抽象方法,则此实现类仍是一个抽象类
  • 一个类可以实现多个接口 —>弥补了Java单继承的局限性
    class A extends B implements C,D
  • 接口和接口之间可以继承,且可以多继承

注意:接口中的属性都是public修饰的,抽象方法也是public

定义一个接口类:

interface Flyable{
	
	//全局常量
	public static final int MAX_SPEED = 7900;
	int MIN_SPEED = 1;
	
	//抽象方法
	public abstract void fly();
	//省略了public abstract修饰,仍是一个抽象方法
	void stop();
	
	//在 JDK 7 之前 接口中只有抽象方法
//	public void eat(){
//		
//	}
	
	//接口中不可以定义构造器Interfaces cannot have constructors
//	public Flyable(){
//		
//	}
	
}

实现接口
若不想实现接口中的所有抽象方法,那该实现类就还是一个抽象类,需要abstract修饰

abstract class Birde implements Flyable{

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}	
}
//实现多个接口,逗号隔开
//需要实现所有接口中的抽象方法,否则该实现类就还是一个抽象类,需要abstract修饰
//若还需要继承其他类,则继承写在接口之前
class Bullet extends Object implements Flyable,Attactable{

	@Override
	public void attact() {
		// TODO Auto-generated method stub	
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
	}
}

接口的多继承性
注意:继承的类也必须都是接口

public interface JDKNewFeature extends USB,NetWork{
...
}

通过接口实例化
我们不能直接去实例化一个接口,因为接口中的方法都是抽象的,是没有方法体的。但是,我们可以使用接口类型的引用指向一个实现了该接口的对象,并且可以调用这个接口中的方法。

public interface JDKNewFeature extends USB,NetWork{

	//静态方法
	public static void method1(){
		System.out.println("JDK8以后,接口中可以写静态方法");
	}	
	//默认方法
	public default void method2(){
		System.out.println("JDK8以后,接口中可以写默认方法");
	}
	
	default void method3(){
		System.out.println("JDK8以后,接口中可以写默认方法,接口若没有些权限修饰符,则权限修饰符为public而不是缺省");
	}
	
}

class Person implements JDKNewFeature{
	@Override
	public void start() {	
	}
	@Override
	public void stop() {	
	}
	@Override
	public void brose() {	
	}
}

class Student{
	@Test
	public void test(){
		JDKNewFeature jdkNF = new Person();
	}
}

Java SE1.8 :除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法

  1. 接口中定义的静态方法只能通过接口调用(接口名.静态方法)
  2. 通过实现类的对象可以调用接口类中的默认方法
  3. 如果实现类重写了接口中的默认方法,那么调用时就是重写后的方法
  4. 如果子类(实现类)继承的父类和实现的接口中声明了同名同参数的方法,在没有重写的情况下,调用的是父类中的方法
  5. 如果实现类实现了多个接口,而这多个接口中出现了同名同参数的默认方法,那么在实现类没有重写该默认方法时调用直接报错(编译不通过) —>接口冲突
  6. 当重写了默认方法以后,若还想调用接口中的方法: 接口名.super.默认方法

(四)接口和抽象类的区别
相同点: 抽象类和接口都不能实例化对象,但是可以定义抽象类和接口类型的引用;
继承抽象类和实现接口都要对其中的抽象方法全部实现;
不同点:

  1. 接口比抽象类更加抽象,抽象类中可以定义构造方法(构造器),可以有抽象方法和具体方法,而接口中的方法全部都是抽象方法(接口中也可以没有方法,这样的接口称为空接口)
  2. 抽象类中的方法可以是private,protected,public,接口全部都是public
  3. 抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量(final)
  4. 有抽象方法的类必须声明为抽象类,而抽象方法未必要有抽象方法

在这里插入图片描述
二、内部类

  • 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

  • Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类

  • Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完
    整的名称。
    Inner class的名字不能与包含它的外部类类名相同;

  • 分类:
    成员内部类(静态和非静态)
    局部内部类(方法内、代码块内、构造器内)
    匿名内部类

  • 成员内部类

  1. 作为内部类的成员:
    ① 可以调用外部类的结构
    ② 可以被static修饰,但此时就不能再使用外层类的非static的成员变量
    ③ 可以被四种权限修饰符修饰
  2. 作为一个类:
    ① 类内可以定义属性、方法、构造器等(也可以继续定义内部类)
    ② 可以被final修饰,表示此类不能被继承,反之可以被继承
    ③ 可以被abstract修饰,因此可以被其它的内部类继承
  • 关于内部类的注意事项
  1. 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员。
  2. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
  3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
  4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的

public class InnerClassTest {

	public static void main(String[] args) {
		
		//创建静态内部类实例
		Person.Bird bird = new Person.Bird();

		//创建非静态的内部类实例
//		Person.Dog dog = new Person.Dog();//编译不通过,非静态的需要通过外部类的对象调用
		Person p = new Person();
		Person.Dog dog = p.new Dog(); 
	}
}

class Person{
	
	String name;
	public void eat(){
		System.out.println("人");
	}
	//非静态成员内部类
	class Dog{
		String name;
		int age;
		//内部类的方法	
		public void show(){
			System.out.println("这一个条狗");
			eat();//非静态内部类可以直接调用
//			this.eat(); //此时是编译报错,this是Dog的对象
			Person.this.eat();//可以通过外部类名.this.外部类的方法调用
		}
		
		public void eat(){
		}
		
	}
	
	//静态成员内部类
	static class Bird{
		
	}
	
	//外部类的方法
	public void method(){
		//局部内部类
		class AA{
			
		}
	}
	
	//非静态代码块
	{
		//局部内部类
		class BB{
			
		}
	}
	
	//构造器
	public Person(){
		//局部内部类
		class CC{
			
		}
	}
	
}
  • 局部内部类的特点
  1. 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号,以及数字编号。
  2. 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类。
  3. 局部内部类可以使用外部类的成员,包括私有的。
  4. 局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的声明周期不同所致。
  5. 局部内部类和局部变量地位类似,不能使用public,protected,缺省,private
  6. 局部内部类不能使用static修饰,因此也不能包含静态成员

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值