Java接口
1.1练习
有了新的需求:
狗 run eat
猫 eat
马 run
人 play feed
实现功能 并且 优化代码
public abstract class Haha {
public abstract void eat();
}
public class Dog extends Haha{
public void eat(){
System.out.println("肉");
}
}
public class Cat extends Haha{
public void eat(){
System.out.println("鱼");
}
}
public class People {
public void feed(Haha h){
h.eat();
}
}
public class JavaTest {
public static void main(String[] args) {
Haha wangcai = new Dog();
Haha kate = new Cat();
People zhangsan = new People();
zhangsan.feed(wangcai);
zhangsan.feed(kate);
}
}
此时我们创建马类 添加run函数
public class Horse {
public void run(){
System.out.println("跑起来");
}
}
此时人类需要和马类玩耍
public class People {
public void feed(Haha h){ h.eat();}
public void play(){}
}
但是人类的play函数 参数类型不知道写什么,因为人类不仅要和马玩耍 还要和狗玩耍,最主要的是 将来谁有play就能和谁玩耍。按照多态的思想 我们需要给这些有play的类添加一个公共父类 产生多态,从而人类play的时候参数类型写公共父类就可以了。
此时我们就需要给 马和狗 找一个公共 父类,但是java中类和类之间的关系是单继承,并且狗已经有父类Haha了 ,而且不能变了(狗的父类Haha是为了和Cat有公共父类产生多态) 马也只能添加父类Haha
但是马一旦添加父类Haha 因为Haha是抽象类 有一个抽象函数eat 所以马就必须的实现eat函数 但是我们的需求中马并没有eat函数
public class Horse extends Haha {
public void run(){
System.out.println("跑起来");
}
@Override
public void eat() {
}
}
此时导致的问题就是: 要想优化代码 单继承解决不了问题。不优化又不能体现面向对象思想.
![]()
1.2 使用接口解决问题
public interface Haha {
void eat();
}
public interface Hehe {
void run();
}
public class Cat implements Haha{
public void eat(){
System.out.println("鱼");
}
}
public class Dog implements Haha,Hehe{
public void eat(){
System.out.println("肉");
}
public void run() {
System.out.println("跑");
}
}
public class Horse implements Hehe {
public void run(){
System.out.println("跑起来");
}
}
public class People {
public void feed(Haha h){
h.eat();
}
public void play(Hehe h){
h.run();
}
}
1.3 接口的简介
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现
Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。
OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为java结构层次上的顶层。
1.4 接口的语法规则
1 接口的声明关键字是 interface
public interface Haha {}
2 接口不能new对象并且也没有构造函数
3 接口中的函数都是抽象的 默认使用public abstract关键字修饰(写不写都是这 并且一般不写)
4 JDK1.8开始有了默认实现函数
public interface Haha {
void eat();
default void aaa(){}
}
5 接口中的变量都是公共静态常量 使用 public static final 修饰 (写不写都是这 并且一般不写)
6 接口和接口之间是继承关系并且是多继承
public interface Heihei extends Haha,Hehe { }
7 接口和类之间的关系是实现关系并且是多实现
public class Dog implements Haha,Hehe{ }
8 普通类实现了接口就需要重写接口中的抽象函数
抽象类 和普通类相比,基本上一样,只有不能new对象并且可以添加抽象函数
接口只有抽象函数和静态常量
1.5 接口的作用
1 产生接口多态 从而解除程序耦合
2 添加标记
3 定制规则(面向接口编程)
1.6 static关键字
public class JavaTest {
public static void main(String[] args) {
Foo f1 = new Foo();
f1.id = 666;
f1.count = 777;
Foo f2 = new Foo();
f2.id = 333;
f2.count = 444;
System.out.println(f1.id+"---"+f1.count);
}
}
public class Foo {
int id;
static int count;
}
静态变量是多个对象共享的
![]()
public class Foo {
public static void haha(){
System.out.println("你好世界");
}
}
public class JavaTest {
public static void main(String[] args) {
Foo.haha();
}
}
什么时候使用静态的 什么时候使用非静态的。
public class Foo {
public void haha(){
System.out.println("你好世界");
}
}
public class JavaTest {
public static void main(String[] args) {
Foo f1 = new Foo();
f1.haha();
}
}
这个地方 都能输出你好世界 此时我们选择使用静态的形式。因为haha是静态函数 直接使用类去调用,所以不需要创建对象,就不需要占据堆区内存。
但是不能理解成 以后所有的函数都要变成静态的,因为有一些函数必须使用对象调用(非静态函数):里面有对应的对象信息
先写出非静态 实现功能 再改成静态的 发现还能行 那就使用静态 如果不行了 非静态
1.7 final最终的
A 类 最终类:这个类没有子类也就是说不能被其他类所继承
public final class Foo {}
面试题: 请问String类能不能被继承?为什么? 为什么String要设计成final的类?
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {}
什么情景中一个类不允许其他类所继承?
B 函数 最终函数:不能被子类重写
C 成员变量/静态变量 常量:只能赋值一次不能被二次修改了
public final void haha(){
int a = 25;
if(a>15){
System.out.println("太棒了");
}
}
代码中出现的 25 15 称之为 魔法值 。这些数字没有语义,所以让代码晦涩难懂
public class Foo {
public static final int MAX_STUDENT_AGE = 15;
public void haha(){
int a = 25;
if(a > MAX_STUDENT_AGE){
System.out.println("太棒了");
}
}
}
一次指的是哪一次?
成员的常量 初始化的时候 或者 构造函数
public class Foo {
public final int MAX_STUDENT_AGE;
public Foo(){
MAX_STUDENT_AGE = 777;
}
}
静态的常量 初始化的时候 或者 静态代码块
public class Foo {
public static final int MAX_STUDENT_AGE;