java之final关键字,接口,多态

final关键字

final关键字是最终的意思,可以修饰(方法,变量,类)

final修饰的特点

修饰方法:表明该方法是最终方法,不能被重写

修饰变量:表明该变量是常量,不能再次被赋值

修饰类:表明该类是最终类,不能被继承

/变量在栈中存

/new出来的东西在堆中存

 基本数据类型变量:其值不能被更改
//常量的命名规范:如果是一个单词,所有字母大写,如果是多个单词,所有字母大写
   //但中间需要使用_分隔
   final int NAX = 10;
   final int MAX_VALUE = 20;
引用数据类型变量:内存地址不能被更改,但是可以修改对象的属性值
    final  Student stu = new Student();
        stu.setName("张三");
        stu.setName("李四");
 //final修饰成员变量 初始化时机
    //1.在创建的时候,直接给值
    //2.在构造方法结束之前,完成赋值

代码块:

{}括起来的代码被称为代码块

局部代码块:

位置:方法中定义的

作用:限定变量的生命周期,及早释放,提高内存利用率

构造代码块:

位置:类中方法外

特点:每次构造方法执行时,都会执行该代码块,并且在构造方法执行前执行

作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性

静态代码块:

位置:类中方法外

特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次

作用:在类加载的时候做一些数据初始化的操作 一般用于安装驱动

接口:

多实现

一个类中,所有的方法,都是抽象方法的时候,我们可以将其定义为接口

接口也是一种引用数据类型,它比抽象类还要抽象

接口存在的两个重要意义

1.规则的定义

2.程序的扩展

接口的定义和特点:

接口用关键字interface来定义

public Interface 接口名{}

接口不能实例化

接口和类之间是实现关系,通过implements关键字表示

public class 类名 implements 接口名{}

接口的子类 (实现类)

要么重写接口中的所有抽象方法

要么是抽象类

例子:

public class Demo1 {
    
    
    public static void main(String[] args) {
    
    
        Cat c = new Cat();
        c.catchMouse();
        Dog d = new Dog();
        d.catchMouse();
    }
}
interface CM{
    
    
    public abstract void catchMouse();//抽象方法
}
class Cat implements CM{
    
    //接口实现

    @Override
    public void catchMouse() {
    
    //重写方法
        System.out.println("猫抓老鼠");
    }
}
class Dog implements CM{
    
    //接口实现

    @Override
    public void catchMouse() {
    
    //重写方法
        System.out.println("狗拿耗子");
    }
}

注意:接口和类的实现关系,可以单实现,也可以多实现.

public class 类名 implements 接口1,接口2{}

public class Test1Interface {
    
    
    /*
    接口定义格式:
    public interface 接口名{}

    类实现接口的格式:
    public class 类名 implements 接口名{}
     */
    public static void main(String[] args) {
    
    
      //Inter i = new Inter();接口不允许创建对象
        InterImpl ii = new InterImpl();
        ii.study();
    }
}
public class InterImpl implements Inter,InterA{
    
    
    @Override
    public void study() {
    
    
        System.out.println("我是实现类中的study方法");
    }

    @Override
    public void print1() {
    
    

    }

    @Override
    public void print2() {
    
    

    }
}
public interface Inter {
    
    
    public abstract void study();
}
public interface InterA {
    
    
    public abstract void print1();
    public abstract void print2();
}
接口中成员的特点:

成员变量:

接口中成员变量只能是常量
系统会默认加入三个关键字:public static final

构造方法:

接口中没有

成员方法:

成员方法:只能是抽象方法,系统会默认给两个关键字
public abstract

public class TestInterface {
    
    
    /*
    接口中成员变量只能是常量,系统会默认加入三个关键字
       public static final
     构造方法:接口中没有
     成员方法:只能是抽象方法,系统会默认给两个关键字
     public abstract
     */
    public static void main(String[] args) {
    
    
        System.out.println(Inter.NUM);
    }
}
class InterImpl extends Object implements Inter{
    
    //所有的类默认的父类是Object
    public InterImpl(){
    
    
        super();
    }
    public void method(){
    
    
        //num = 20;
        System.out.println(NUM);
    }

    @Override
    public void show() {
    
    

    }
}
interface Inter  {
    
    
    //接口中的变量是常量,默认会被final,static,public关键字修饰
    public static final int NUM = 10;
    //public Inter(){}
    public abstract void show();
}

JDK8版本中接口成员的特点:

JDK8版本后:

1.允许在接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法是默认方法

作用:解决接口升级的问题

2.接口中允许定义static静态方法

接口中默认方法的定义格式:

格式:public default 返回值类型方法名(参数列表){}

范例:public default void show() {}

接口中默认方法的注意事项:

默认方法不是抽象方法,所以不强制被重写.但是可以被重写,重写的时候去掉default关键字

public可以省略,default不能省略

如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写

接口中静态方法的注意事项:

1.静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

2.public可以省略,static不能省略

类和接口的关系:

类和类的关系:

继承关系,只能单继承,但是可以多层继承

类和接口的关系:

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同事实现多个接口

//如果父类和接口出现相同的方法声明,父类的

接口和接口的关系:

继承关系,可以单继承,也可以多继承

多态:

传参数传父类

父类引用指向子类对象

同一个对象,在不同时刻表现出来的不同形态

举例:猫

我们可以说猫是猫:猫 cat = new 猫();

我们也可以说猫是动物:动物 animal = new 猫();

这里的猫在不同时刻表现出来了不同的形态,这就是多态

多态的前提和体现:

有继承/实现关系

有方法重写

有父类引用指向子类对象

例子:

public class Test1Polymorphic {
    
    
    /*
    多态的前提:
    1.要有(继承\实现)关系
    2.要有方法重写
    3.要有父类引用,指向子类对象

     */
    public static void main(String[] args) {
    
    

        //当前事物是一只猫
        Cat c = new Cat();
        //当前事物是一只动物
        Animal a = new Cat();
        a.eat();
    }
}
class Animal{
    
    
    public void eat(){
    
    
        System.out.println("动物吃饭");
    }
}
class Cat extends Animal{
    
    
    @Override
    public void eat() {
    
    
        System.out.println("猫吃鱼");
    }
}

多态中成员访问的特点:

构造方法:同继承一样,子类会通过super访问父类构造方法

成员变量:编译看左边(父类),执行看左边(父类)

成员方法:编译看左边(父类),执行看右边(父类)

public class Test2Polymorphic {
    
    
    /*
    多态成员访问特点:
    成员变量:编译看左边(父类),执行看左边(父类)
    成员方法:编译看左边(父类),执行看右边(父类)
     */
    public static void main(String[] args) {
    
    
        Fu f =new Zi();
        System.out.println(f.num);//10,但必须有父类中的num
        f.method();//Zi...method   父类中必须有method()方法
    }
}
class Fu{
    
    
    int num =10;
    public  void method(){
    
    
        System.out.println("Fu...method");
    }
}
class Zi extends Fu{
    
    
    int num = 20;
    public void method(){
    
    
        System.out.println("Zi...method");
    }
}

为什么成员变量和成员方法的访问不一样呢?

1.因为成员方法有重写,而成员变量没有

多态的好处和弊端:

好处:提高代码的扩展性

具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接受这父类的任意子对象

弊端:不能调用子类特有的功能

例子:

public class Test3Polymorphic {
    
    
    public static void main(String[] args) {
    
    
        useAnimal(new Dog());
        useAnimal(new Cat());
    }
    public  static  void useAnimal(Animal a){
    
    
        a.eat();
    }
}
abstract class Animal{
    
    
    public abstract void eat();
}
class Dog extends Animal{
    
    

    @Override
    public void eat() {
    
    
        System.out.println("狗吃肉");
    }
}
class  Cat extends Animal{
    
    

    @Override
    public void eat() {
    
    
        System.out.println("猫吃鱼");
    }
}

多态中的转型:

向上转型:从子到父

父类引用指向子类对象

向下转型:从父到子

父类引用转为子类对象

例子:

public class Test4Polymorpic {
    
    
    public static void main(String[] args) {
    
    
        //1.向上转型:从子到父
        //     父类引用指向子类对象

        Fu f = new Zi();
        f.show();
        //多态的弊端 不能调用子类特有的功能
        //f.method();

        //A.直接创建子类对象
        //B.向下转型
        //2.向下转型:从父到子
        //   父类引用转为子类对象  强制转换
        Zi z = (Zi)f;
        z.method();
    }
}
class Fu{
    
    

    public  void show(){
    
    

        System.out.println("Fu...show");
    }
}
class Zi extends Fu {
    
    
    @Override
    public void show()
    {
    
    
        System.out.println("Zi...show");
    }

    public void method() {
    
    
        System.out.println("我是子类特有的方法,method");
    }
}
多态中的转型存在的风险

如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,name在转换的时候就会出现ClassCastException

避免强转出现的问题

关键字:instanceof

使用格式:

变量名 instanceof 类型

通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果

例子:

public class Test3Polymorphic {
    
    
    public static void main(String[] args) {
    
    
        useAnimal(new Dog());
        useAnimal(new Cat());
    }
    public  static  void useAnimal(Animal a){
    
    

        a.eat();
        if(a instanceof  Dog){
    
    
            Dog dog = (Dog) a;
            dog.watchHome();//ClassCastException类型转换异常
        }
       // Dog dog = (Dog) a;
       // dog.watchHome();//ClassCastException类型转换异常
    }
}
abstract class Animal{
    
    
    public abstract void eat();
}
class Dog extends Animal{
    
    

    @Override
    public void eat() {
    
    

        System.out.println("狗吃肉");
    }
    public void watchHome() {
    
    

        System.out.println("看门");
    }

}
class  Cat extends Animal{
    
    

    @Override
    public void eat() {
    
    

        System.out.println("猫吃鱼");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42073385/article/details/108039626