总结:
1. 类与类的关系
继承关系,只支持单继承
比如,A是子类 B是父类,A具备B所有的功能(除了父类的私有资源和构造方法)
子类如果要修改原有功能,需要重写(方法签名与父类一致 + 权限修饰符>=父类修饰符)
2. 类和接口的关系
实现关系.可以单实现,也可以多实现
class A implements B,C{}
其中A是实现类,B和C是接口,A拥有BC接口的所有功能,只是需要进行方法的重写,否则A就是抽象类
3. 接口与接口的关系
是继承关系,可以单继承,也可以多继承
interface A extends B,C{}
其中ABC都是接口,A是子接口,具有BC接口的所有功能(抽象方法)
class X implements A{}
X实现类需要重写ABC接口的所有方法,否则就是抽象类
class A extends B implements C,D{}
其中A是实现类,也是B的子类,同时拥有CD接口的所有功能
这时A需要重写CD接口里的所有抽象方法
4. 抽象类与接口的区别
抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)
接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法
接口会为方法自动拼接public abstract,还会为变量自动拼接public final static
抽象类可以有成员变量成员常量 接口只能有静态常量
抽象类可以有构造方法–用来给子类创建对象,接口中没有构造方法
抽象类和接口都不能实例化(创建对象)
接口可继承接口,并可多继承接口,但类只能单继承
抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果
复习:
1.接口的特点:
我们使用interface关键字定义接口
我们使用implements关键字建立接口实现类与接口的实现关系
接口是父级,接口实现类是子级
接口实现类如果实现部分/不实现接口中的抽象方法,那么实现类是一个抽象类
接口实现类如果实现了接口所有的抽象方法,那么这个实现类是一个普通类
抽象类与接口都不可以实例化/创建对象
接口没有构造函数,实现类使用的super()是父类的无参构造
如果没有明确指定父类,super()代表的才是Object的无参构造
接口中都是静态常量,没有成员变量,因为会默认拼接public static final
接口中都是抽象方法,默认会拼接public abstract
故此:静态常量与抽象方法默认拼接的部分,可以省略不写
接口不是类!!!
接口是用来制定规则的【有哪些功能?方法有参数吗?有返回值吗?】
方法具体的实现交给接口的实现类去完成
2. 接口与类的关系
1.类与类的关系
继承关系,只支持单继承
2.类与接口的关系
实现关系,可以单实现,也可以多实现
class A implements Inter1{}–单实现
class B implements Inter2,Inter3{}–多实现
3.接口与接口的关系
是继承关系,可以单继承,也可以多继承
interface Inter3 extends Inter1{}–接口的单继承
interface Inter4 extends Inter1,Inter2{}–接口的多继承
注意:如果创建接口实现类的话:
Inter3Impl只需要实现接口3与接口1的抽象方法
Inter4Impl不仅需要实现接口4,还需要实现接口4继承自接口1与接口2的所有功能
3. 抽象类与接口的区别:
抽象类使用class关键字定义,是类
接口使用interface关键字定义,是接口
2.抽象类里可以定义成员变量
接口里没有成员变量,有的是静态常量,默认会拼接public static final
3.抽象类里的方法不作限制:全普、全抽、半普半抽
接口中的方法都是抽象方法,默认会拼接:public abstract
4.抽象类与接口均不可以实例化/创建对象
5.抽象类里有构造方法,不是为了自己使用,而是为了子类创建对象时调用
接口里没有构造方法,接口实现类调用的构造是父类的构造方法,与接口无关
6.接口可以多继承,也就是说,一个接口可以继承一个接口/多个接口
抽象类只能单继承,也就是说,一个子类只能有一个父类
7.抽象是后天重构的结果,接口是先天设计的结果
package cn.tedu.innerclass;
public class TestInner1 {
public static void main(String[] args) {
//在main()方法中创建内部类对象,使用内部类资源
Outer.Inner oi = new Outer().new Inner();
oi.delete();
System.out.println(oi.sum);
Outer O=new Outer();
O .find();
}
}
class Outer{
String name;
private int age;
public void find(){
System.out.println("Outer类的find()");
/*外部类不可以直接使用内部类的资源,如过想要使用,必须先创建内部类对象*/
Inner i=new Inner();
System.out.println(i.sum);
i.delete();
}
/**
* 根据内部类位置的不同,分为
* 成员内部类:类里方法外。
* 局部内部类:方法里
*/
class Inner{
int sum=10;
public void delete(){
System.out.println("Inner的delete()");
/*内部类可以直接使用外部类的资源,包括私有资源*/
System.out.println(name);
System.out.println(age);
}
}
}
Inner的delete()
null
0
10
Outer类的find()
10
Inner的delete()
null
0
内部类:
1) 内部类可以直接访问外部类中的成员,包括私有成员
总结:
成员内部类被Private修饰以后,无法被外界直接创建对象使用
package cn.tedu.innerclass;
public class TestInner3 {
public static void main(String[] args) {
//创建普通内部类对象并调用内部类的功能
// Outer3.Inner3 oi=new Outer3().new Inner3();
// oi.show();
// new Outer3().new Inner3().show();
/*当成员内部类被static修饰后,new Outer3()外部类对象会报错,
* 结论:创建静态内部类对象时,不需要先创建外部类对象,直接通过类名调用*/
Outer3.Inner3 inner3 = new Outer3.Inner3();
inner3.show();
new Outer3.Inner3().show();
//访问静态内部类的静态资源----链式加载
Outer3.Inner3.show2();
}
}
class Outer3{
//测试成员内部类被static修饰--并不常用
static class Inner3{
public void show(){
System.out.println("Inner3的show()");
}
//创建成员内部类的静态方法
public static void show2(){
System.out.println("Inner3的show2()");
}
}
}
Inner3的show()
Inner3的show()
总结:
访问静态类中的静态资源可以通过”. . . ”链式加载的方式访问
package cn.tedu.innerclass;
/*本类用于测试成员内部类被private修饰*/
public class TestInner2 {
/*如果Inner2被private修饰,无法直接创建对象,该怎么办?*/
public static void main(String[] args) {
new Outer2().getInner2();
}
}
class Outer2{
/*提供本类的公共方法,在本方法内部创建内部类的对象,使用内部类的功能*/
public void getInner2(){
Inner2 i=new Inner2();
i.eat();
}
private class Inner2{
public void eat(){
System.out.println("Inner2的eat()");
}
}
}
Inner2的eat()
局部内部类:
package cn.tedu.innerclass;
/*本类用来测试局部内部类*/
public class Testinner4 {
public static void main(String[] args){
/**
* 如何使用局部内部类的资源呢?
* 注意:直接调用外部类的show()是无法触发局部内部类的功能的
* 要执行局部内部类的功能,必须先创建局部内部类的对象并调用对应的功能
* 创建局部内部类对象,并调用局部内部类的功能
*/
new Outer4().show();
}
}
class Outer4{
//创建外部类的成员方法
public void show(){
System.out.println("Outer4的show()");
class Inner4{
String name;
int age;
public void eat(){
System.out.println("Inter4的eat()");
}
}
Inner4 in = new Inner4();
in.eat();
System.out.println(in.age);
System.out.println(in.name);
}
}
Outer4的show()
Inter4的eat()
0
null
匿名内部类没有名字,通常与匿名对象结合在一起使用
匿名对象只能使用一次,一次只能调用一个功能
匿名内部类充当了实现类的角色,去实现接口/抽象类中的抽象方法,只是没有名字而言。
package cn.tedu.innerclass;
public class TestInner5 {
public static void main(String[] args) {
//传统方式:创建接口+创建接口实现类+实现类实现接口中所有的抽象方法
//创建接口实现类的对象+通过对象调用实现了的功能
/**
* 创建接口对应的匿名对象与匿名内部类,并调用实现后的save()
*/
new Inter1() {
@Override
public void save() {
System.out.println("保存");
}
@Override
public void get() {
System.out.println("获取");
}
}.save();
/**
* 创建抽象类对应的匿名对象和匿名内部类
*/
new Inter2(){
public void set(){
System.out.println("set()方法实现了");
}
}.set();
new Inter3().study();
}
}
interface Inter1 {
void save();
void get();
}
abstract class Inter2{
public void play(){
System.out.println("玩代码");
}
abstract public void set();
}
class Inter3{
public void study(){
System.out.println("再冷的天也阻挡不了我学习的热情");
}
public void powerUp(){
System.out.println("我们会越来越强的! ");
}
}
保存
set()方法实现了
再冷的天也阻挡不了我学习的热情