下面程序结果
Demo2_Student静态代码块
我是main方法
Student 静态代码块
Student 构造代码块
Student 构造方法
Student 构造代码块
Student 构造方法
class Student {
static {
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 构造代码块");
}
public Student() {
System.out.println("Student 构造方法");
}
}
class Demo2_Student {
static {
System.out.println("Demo2_Student静态代码块");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
继承案例演示
- A:继承(extends)
- 让类与类之间产生关系,子父类关系
- B:继承案例演示:
- 动物类,猫类,狗类
- 定义两个属性(颜色,腿的个数)两个功能(吃饭,睡觉)
- C:案例演示
- 使用继承前
- D:案例演示
- 使用继承后
class Demo1_Extends {
public static void main(String[] args) {
Cat c = new Cat();
c.color = "red";
c.leg = 4;
c.eat();
c.sleep();
}
}
class Animal {
String color; //动物的颜色
int leg; //动物腿的个数
public void eat() { //吃饭的功能
System.out.println("吃饭");
}
public void sleep(){ //睡觉的功能
System.out.println("睡觉");
}
}
class Cat extends Animal {}
class Dog extends Animal {}
/*
extends是继承的意思
Animal是父类
Cat和Dog都是子类
*/
继承的好处和弊端
- A:继承的好处
- a:提高了代码的复用性
- b:提高了代码的维护性
- c:让类与类之间产生了关系,是多态的前提
- B:继承的弊端
类的耦合性增强了。
开发的原则:高内聚,低耦合。
耦合:类与类的关系
内聚:就是自己完成某件事情的能力
Java中类的继承特点
- A:Java中类的继承特点
- a:Java只支持单继承,不支持多继承。(一个儿子只能有一个爹)
- 有些语言是支持多继承,格式:extends 类1,类2,...
- b:Java支持多层继承(继承体系)
- a:Java只支持单继承,不支持多继承。(一个儿子只能有一个爹)
- B:案例演示
- Java中类的继承特点
- 如果想用这个体系的所有功能用最底层的类创建对象
- 如果想看这个体系的共性功能,看最顶层的类
- Java中类的继承特点
class Demo2_Extends {
public static void main(String[] args) {
DemoC d = new DemoC();
d.show();
}
}
class DemoA {
public void show() {
System.out.println("DemoA");
}
}
class DemoB {
public void show() {
System.out.println("DemoA");
}
}
class DemoC extends DemoA,DemoB {
}
/*
Demo2_Extends.java:20: 错误: 需要'{'
class DemoC extends DemoA, DemoB {
^
*/
继承的注意事项和什么时候使用继承
-
A:继承的注意事项
- a:子类只能继承父类所有非私有的成员(成员方法和成员变量)
- b:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
- c:不要为了部分功能而去继承
- 项目经理 姓名 工号 工资 奖金
- 程序员 姓名 工号 工资
-
B:什么时候使用继承
- 继承其实体现的是一种关系:"is a"。
Person
Student
Teacher
水果
苹果
香蕉
橘子
采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。 - 继承其实体现的是一种关系:"is a"。
继承中成员变量的关系
- A:案例演示
- a:不同名的变量
- b:同名的变量
class Demo4_Extends {
public static void main(String[] args) {
Son s = new Son();
s.print();
}
}
class Father {
int num1 = 10;
int num2 = 30;
}
class Son extends Father {
int num2 = 20;
public void print() {
System.out.println(num1); //10
System.out.println(num2); //就近原则,子类有就不用父类的了
}
}
//子父类出现同名的变量只是在讲课中举例子有,在开发中是不会出现这种情况的
//子类继承父类就是为了使用父类的成员,那么如果定义了同名的成员变量就没有意义了
this和super的区别和应用
- A:this和super都代表什么
- this:代表当前对象的引用,谁来调用我,我就代表谁
- super:代表当前对象父类的引用
- B:this和super的使用区别
- a:调用成员变量
- this.成员变量 调用本类的成员变量,也可以调用父类的成员变量(本类没有的情况下)
- super.成员变量 调用父类的成员变量
- b:调用构造方法
- this(...) 调用本类的构造方法
- super(...) 调用父类的构造方法
- c:调用成员方法
- this.成员方法 调用本类的成员方法,也可以调用父类的方法
- super.成员方法 调用父类的成员方法
- a:调用成员变量
继承中构造方法的关系
- A:案例演示
- 子类中所有的构造方法默认都会访问父类中空参数的构造方法
- B:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
-
其实:
- 每一个构造方法的第一条语句默认都是:super() Object类最顶层的父类
class Demo5_extends {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father {
public Father() {
System.out.println("Father的构造方法");
}
}
class Son extends Father {
public Son() {
super(); //这是一条语句,如果不写,系统会默认加上,用来访问父类的空参构造
System.out.println("Son的构造方法");
}
}
class Demo6_Extends {
public static void main(String[] args) {
Son s1 = new Son();
Son s2 = new Son("张三",23);
}
}
class Father {
private String name;
private int age;
public Father() {
System.out.println("Father 空参构造");
}
public Father(String name,int age) {
this.name = name;
this.age = age;
System.out.println("Father 有参构造");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
class Son extends Father {
public Son() { //空参构造
super(); //这是一条语句,如果不写,系统会默认加上,用来访问父类的空参构
System.out.println("Son 空参构造");
}
public Son(String name,int age) { //有参构造
super(); //这是一条语句,如果不写,系统会默认加上,用来访问父类的空参构
System.out.println("Son 有参构造");
}
}
继承中构造方法的注意事项
- A:案例演示
- 父类没有无参构造方法,子类怎么办?
- super解决
- this解决
- B:注意事项
- super(…)或者this(….)必须出现在构造方法的第一条语句上,所以这两者不能共存。
class Demo6_Extends {
public static void main(String[] args) {
Son s1 = new Son();
System.out.println(s1.getName() + "..." + s1.getAge());
Son s2 = new Son("张三",23);
System.out.println(s2.getName() + "..." + s2.getAge());
}
}
class Father {
private String name;
private int age;
/*public Father() {
System.out.println("Father 空参构造");
}*/
public Father(String name,int age) {
this.name = name;
this.age = age;
System.out.println("Father 有参构造");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
class Son extends Father {
public Son() { //空参构造
//super("李四",24); //调用父类中的构造方法
this("王五",25); //调用本类中的构造方法
System.out.println("Son 空参构造");
}
public Son(String name,int age) { //有参构造
super(name,age);
System.out.println("Son 有参构造");
}
}
继承的例子
class Demo6_Extends {
public static void main(String[] args) {
Zi z = new Zi();
}
/*
1,jvm调用了main方法,main进栈
2,遇到Zi z = new Zi();会先将Fu.class和Zi.class分别加载进内存,再创建对象,当Fu.class
加载进内存,父类的静态代码块会随着Fu.class一起加载,当Zi.class加载进内存,子类的静态
代码块会随着Zi.class一起加载,第一个输出静态代码块Fu,第二个输出静态代码块Zi
3,走Zi类的构造方法,因为java中是分层初始化的,先初始化父类,再初始化子类,所以先走的
父类构造,但是再执行父类构造时,发现父类有构造代码块,构造代码块是优先于构造方法执行的
所以第三个输出构造代码块Fu,第四个输出构造方法Fu
4,Fu类初始化结束,子类初始化,第五个输出的是构造代码块Zi,构造方法Zi
*/
}
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
继承中成员方法关系
- A:案例演示
- a:不同名的方法
- b:同名的方法
方法重写概述及其应用
- A:什么是方法重写
- 重写:子父类出现了一模一样的方法(注意:返回值类型可以是子父类,这个我们学完面向对象讲)
- B:方法重写的应用:
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
class Demo7_Extends {
public static void main(String[] args) {
Son s = new Son();
s.print();
s.method();
}
}
class Father {
public void print() {
System.out.println("Fu print");
}
}
class Son extends Father {
public void method() {
System.out.println("Zi method");
}
public void print() {
super.print(); //super可以调用父类的成员方法
System.out.println("Zi print");
}
}
方法重写的注意事项
- A:方法重写注意事项
-
a:父类中私有方法不能被重写
- 因为父类私有方法子类根本就无法继承
-
b:子类重写父类方法时,访问权限不能更低
- 最好就一致
-
c:父类静态方法,子类也必须通过静态方法进行重写 (若子类是静态方法呢?)
- 其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态,其实不算重写,多态时候详细讲解)
子类重写父类方法的时候,最好声明一模一样。
-
- B:案例演示
- 方法重写注意事项
方法重写的面试题
- A:方法重写的面试题
Override和Overload的区别?Overload能改变返回值类型吗?
overload可以改变返回值类型,只看参数列表,与返回值类型无关
方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值类型有关,返回值是一致(或者是子父类)的
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值类型无关。
-
子类对象调用方法的时候:
- 先找子类本身,再找父类。
实例
class Test4_Person {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("张三");
s1.setAge(23);
System.out.println(s1.getName() + "..." + s1.getAge());
s1.eat();
s1.study();
Student s2 = new Student("李四",24);
System.out.println(s2.getName() + "..." + s2.getAge());
s1.eat();
s1.study();
}
}
class Person {
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void eat() {
System.out.println(name + "吃饭");
}
}
class Student extends Person {
public Student() {} //空参构造
public Student(String name,int age) {
super(name,age);
}
public void study() {
System.out.println(super.getName() + "学习"); //这里super.getName()和this.getName()都可以,一个是直接访问一个是继承,但是效果一致。
}
}
class Teacher extends Person {
public Teacher() {} //空参构造
public Teacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println(getName() + "教书"); //getName()等效于this.getName()
}
}
final关键字修饰类,方法以及变量的特点
- A:final概述
- B:final修饰特点
- 修饰类,类不能被继承
- 修饰变量,变量就变成了常量,只能被赋值一次
- 修饰方法,方法不能被重写
final关键字修饰局部变量
- A:案例演示
方法内部或者方法声明上都演示一下(了解)
基本类型,是值不能被改变
引用类型,是地址值不能被改变,对象中的属性可以改变
class Demo2_Final {
public static void main(String[] args) {
final int NUM = 10;
//NUM = 20;
System.out.println(NUM);
final Person p = new Person("张三",23);
//p = new Person("李四",24);
p.setName("李四");
p.setAge(24);
System.out.println(p.getName() + "..." + p.getAge());
method(10);
method(20); //不会报错,因为上面方法调用完后会弹栈
}
public static void method(final int x) {
System.out.println(x);
}
}
class Person {
private String name;
private int age;
public Person() {}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
final修饰变量的初始化时机
- A:final修饰变量的初始化时机
- 显示初始化
- 在对象构造完毕前即可
class Demo3_Final {
public static void main(String[] args) {
Demo d = new Demo();
d.print();
}
}
class Demo {
//final int NUM = 10; //1.显示初始化
//final int NUM //成员变量的默认初始化值是无效值
final int NUM; //2.在对象构造中初始化
public Demo() {
NUM = 10;
}
public void print() {
System.out.println(NUM);
}
}
多态的概述及其代码体现
- A:多态(polymorphic)概述
- 事物存在的多种形态
- B:多态前提
- a:要有继承关系。
- b:要有方法重写。
- c:要有父类引用指向子类对象。
class Demo1_Polymorphic {
public static void main(String[] args) {
Cat c = new Cat();
c.eat();
Animal a = new Cat(); //父类引用指向子类对象
a.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
多态中的成员访问特点之成员变量和成员方法
- 成员变量
- 编译看左边(父类),运行看左边(父类)。
- 成员方法
- 编译看左边(父类)(确保父类中有这个方法),运行看右边(子类)。(动态绑定)
class Demo2_Polymorphic {
public static void main(String[] args) {
Father f1 = new Son(); //父类引用指向子类对象
System.out.println(f1.num);
Son s = new Son();
System.out.println(s.num);
Father f2 = new Son();
f2.print();
}
}
class Father {
int num = 10;
public void print() {
System.out.println("father");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("son");
}
}
多态中的成员访问特点之静态成员方法
- 静态方法
- 编译看左边(父类),运行看左边(父类)。
- (静态和类相关,算不上重写,所以,访问还是左边的)
- 只有非静态的成员方法,编译看左边,运行看右边
class Demo2_Polymorphic {
public static void main(String[] args) {
Father f1 = new Son(); //父类引用指向子类对象
System.out.println(f1.num);
Son s = new Son();
System.out.println(s.num);
Father f2 = new Son();
f2.print();
f2.method(); //相当于是Father.method()
}
}
class Father {
int num = 10;
public void print() {
System.out.println("father");
}
public static void method() {
System.out.println("father static method");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("son");
}
public static void methog() {
System.out.println("son static method");
}
}
多态中向上转型和向下转型
- A:案例演示
- 详细讲解多态中向上转型和向下转型
Person p = new SuperMan();向上转型
SuperMan sm = (SuperMan)p;向下转型
- 详细讲解多态中向上转型和向下转型
class Demo3_superMan {
public static void main(String[] args) {
Person p = new SuperMan(); //父类引用指向子类对象,超人提升为了人
System.out.println(p.name); //父类引用指向子类对象就是向上转型
p.business();
SuperMan sm = (SuperMan) p; //向下转型
sm.fly();
}
}
class Person {
String name = "John";
public void business() {
System.out.println("谈生意");
}
}
class SuperMan extends Person {
String name = "superMan";
public void business() {
System.out.println("谈几个亿的大单子");
}
public void fly() {
System.out.println("飞出去救人");
}
}
多态的好处和弊端
- A:多态的好处
- a:提高了代码的维护性(继承保证)
- b:提高了代码的扩展性(由多态保证)
- B:案例演示
- 多态的好处
- 可以当作形式参数,可以接收任意子类对象
- C:多态的弊端
- 不能使用子类的特有属性和行为。
class Demo4_Animal {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
//Animal a = new Cat(); 开发的时候很少在创建对象的时候用父类引用指向子类对象,直接创建子类对象更方便,可以使用子类中的特有属性和行为
}
//如果把狗强转成猫就会出现类型转换异常,ClassCastException
public static void method(Animal a) { //当作参数的时候用多态最好,因为扩展性强
//Cat c = (Cat)a;
//关键字 instanceof 判断前边的引用是否是后边的数据类型
if (a instanceof Cat) {
Cat c = (Cat)a;
c.eat();
c.catchMouse();
}else if (a instanceof Dog) {
Dog d = (Dog)a;
d.eat();
d.lookHome();
}else {
a.eat();
}
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("看家");
}
}
多态中的题目分析题
- A:看下面程序是否有问题,如果没有,说出结果
class Fu { public void show() { System.out.println("fu show"); } } class Zi extends Fu { public void show() { System.out.println("zi show"); } public void method() { System.out.println("zi method"); } } class Test1Demo { public static void main(String[] args) { Fu f = new Zi(); f.method(); f.show(); } }
- B:看下面程序是否有问题,如果没有,说出结果
class A { public void show() { show2(); } public void show2() { System.out.println("我"); } } class B extends A { public void show2() { System.out.println("爱"); } } class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你"); } } public class Test2DuoTai { public static void main(String[] args) { A a = new B(); a.show(); B b = new C(); b.show(); } }
自己的猜测:结果分析,继承相当于是将父类的代码拷贝到子类,所以是先看子类有没有此方法,没有在看父类有没有这个方法,如果有运行结果等价于(将代码拷贝到子类运行)
抽象类的概述及其特点
- A:抽象类概述
- 抽象就是看不懂的
- B:抽象类特点
- a:抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名 {}
- public abstract void eat();
- b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
- c:抽象类不能实例化那么,抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- d:抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法
- a:抽象类和抽象方法必须用abstract关键字修饰
- C:案例演示
- 抽象类特点B:抽象类特点
- a:抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名 {}
- public abstract void eat();
- b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
- c:抽象类不能实例化那么,抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- d:抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法
class Demo1_Abstract {
public static void main(String[] args) {
//Animal a = new Animal();//错误: Animal是抽象的; 无法实例化
Animal a = new Cat(); //抽象类实例化,父类引用指向子类对象
a.eat();
}
}
abstract class Animal { //抽象类
public abstract void eat(); //抽象方法
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
抽象类的成员特点
- A:抽象类的成员特点
- a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员变量
- b:构造方法:有。
- 用于子类访问父类数据的初始化。
- c:成员方法:既可以是抽象的,也可以是非抽象的。
- B:案例演示
- 抽象类的成员特点
- C:抽象类的成员方法特性:
- a:抽象方法 强制要求子类做的事情。
- b:非抽象方法 子类继承的事情,提高代码复用性。
class Demo2_Abstract {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
abstract class Demo {
int num1 = 10;
final int NUM2 = 20;
public Demo(){}
public void print() {
System.out.println("111");
}
public abstract void method();
}
class Test extends Demo {
public void method() {
System.out.println("111");
}
}
抽象类练习猫狗案例
class Test1_Animal {
public static void main(String[] args) {
Cat c = new Cat("加菲",8);
System.out.println(c.getName() + "..." + c.getAge());
c.eat();
c.catchMouse();
Dog d = new Dog("八公",30);
System.out.println(d.getName() + "..." + d.getAge());
d.eat();
d.lookHome();
}
}
abstract class Animal {
private String name;
private int age;
public Animal(){} //空参
public Animal(String name,int age) { //有参
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public abstract void eat();
}
class Cat extends Animal {
public Cat(){} //空参
public Cat(String name,int age) { //有参
super(name,age);
}
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public Dog(){} //空参
public Dog(String name,int age) { //有参
super(name,age);
}
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("看家");
}
}
抽象类练习员工案例
- A:案例演示
- 假如我们在开发一个系统时需要对程序员类进行设计,程序员包含3个属性:姓名、工号以及工资。
- 经理,除了含有程序员的属性外,另为还有一个奖金属性。
- 请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
class Test3_Employee {
public static void main(String[] args) {
Coder c = new Coder("德玛西亚","007",8000);
c.work();
Manager m = new Manager("苍老师","9527",3000,20000);
m.work();
}
}
abstract class Employee {
private String name;
private String id;
private double salary;
public Employee() {}
public Employee(String name,String id,double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
public abstract void work();
}
class Coder extends Employee {
public Coder() {}
public Coder(String name,String id,double salary) {
super(name,id,salary);
}
public void work() {
System.out.println(this.getName() + this.getId() + this.getSalary() + "敲代码");
}
}
class Manager extends Employee {
private int bonus; //奖金
public Manager() {}
public Manager(String name,String id,double salary,int bonus) {
super(name,id,salary);
this.bonus = bonus;
}
public void work() {
System.out.println(this.getName() + this.getId() + this.getSalary() + bonus +"管理");
}
}
抽象类中的面试题
- A:面试题1
- 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
- 可以
- 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
- B:面试题2
- abstract不能和哪些关键字共存
abstract和static
被abstrac修饰的方法没有方法体
被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的
abstract和final
被abstract修饰的方法强制子类重写
被final修饰的不让子类重写,所以矛盾
abstract和private
被abstract修饰的是为了让子类看到并强制重写
被private修饰不让子类访问,所以矛盾
- abstract不能和哪些关键字共存
class Demo4_Abstract {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
abstract class Demo {
//public static abstract void print();//错误: 非法的修饰符组合: abstract和static
//public final abstract void print();//错误: 非法的修饰符组合: abstract和final
//private abstract void print();//错误: 非法的修饰符组合: abstract和private
}
接口的概述及其特点
A:接口概述
* 从狭义的角度讲就是指java中的interface
* 从广义的角度讲对外提供规则的都是接口
- B:接口特点
- a:接口用关键字interface表示
- interface 接口名 {}
- b:类实现接口用implements表示
- class 类名 implements 接口名 {}
- c:接口不能实例化
- 那么,接口如何实例化呢?
- 按照多态的方式来实例化。
- d:接口的子类
- a:可以是抽象类。但是意义不大。
- b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
- a:接口用关键字interface表示
接口的成员特点
A:接口成员特点
* 成员变量;只能是常量,并且是静态的并公共的。
* 默认修饰符:public static final
* 建议:自己手动给出。
* 构造方法:接口没有构造方法。
* 成员方法:只能是抽象方法。
* 默认修饰符:public abstract
* 建议:自己手动给出。
class Demo2_Interface {
public static void main(String[] args) {
Demo d = new Demo();
d.print();
System.out.println(Inter.num);
}
}
interface Inter {
public static final int num = 10; //public static和final如果不加,系统会默认加上,顺序可以交换
//public Inter(){} //接口中没有构造方法
/*public void print() { //接口中不能定义非抽象方法
} */
public abstract void print(); //public和abstract如果不加,系统会默认加上
}
class Demo /*extends Object*/ implements Inter { //一个类不写继承任何类,默认继承Object类
public void print() {
System.out.println(num);
}
}
类与类,类与接口,接口与接口的关系
- A:类与类,类与接口,接口与接口的关系
- a:类与类:
- 继承关系,只能单继承,可以多层继承。
- b:类与接口:
- 实现关系,可以单实现,也可以多实现。
- 并且还可以在继承一个类的同时实现多个接口。
- c:接口与接口:
- 继承关系,可以单继承,也可以多继承。
- a:类与类:
class Demo3_Interface {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
interface InterA {
public abstract void printA();
}
interface InterB {
public abstract void printB();
}
interface InterC extends InterB,InterA {
}
class Demo extends Object implements InterA,InterB {
public void printA() {
System.out.println("printA");
}
public void printB() {
System.out.println("printB");
}
}
抽象类和接口的区别
-
A:成员区别
- 抽象类:
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口:
- 成员变量:只可以常量
- 成员方法:只可以抽象
- 抽象类:
-
B:关系区别
- 类与类
- 继承,单继承
- 类与接口
- 实现,单实现,多实现
- 接口与接口
- 继承,单继承,多继承
- 类与类
-
C:设计理念区别
- 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
- 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
猫狗案例加入跳高功能分析及其代码实现
class Test1_Animals {
public static void main(String[] args) {
Cat c = new Cat("加菲",8);
c.eat();
c.sleep();
JumpCat jc = new JumpCat("跳高猫",3);
jc.eat();
jc.sleep();
jc.jump();
}
}
abstract class Animal {
private String name;
private int age;
public Animal() {} //空参构造
public Animal(String name,int age) { //有参构造
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public abstract void eat();
public abstract void sleep();
}
interface Jumping {
public void jump();
}
class Cat extends Animal {
public Cat() {}
public Cat(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("猫吃鱼");
}
public void sleep() {
System.out.println("侧着睡");
}
}
class JumpCat extends Cat implements Jumping {
public JumpCat() {}
public JumpCat(String name,int age) {
super(name,age);
}
public void jump() {
System.out.println("猫跳高");
}
}