JavaSE学习(Day05)【多态】【final关键字】【Java中的四种权限修饰符】

文章目录

  • 多态
  • final关键字
  • Java中的四种权限修饰符

多态

代码当中体现多态性,其实就是一句话:父类引用指向子类对象
格式:

父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();

new谁就调用谁的方法(没有向上找),引用是谁,就用谁的成员和静态。
花木兰打仗用的是自己的方法,用的是父亲的信息.

口诀:编译(是否变红)看左,运行看右

成员变量:编译看左边,运行还看左边
成员方法:编译看左,运行看右边

多态存在要有3个必要条件

1、继承
2、方法重写
3、父类引用指向子类对象。
public class Fu {
     
    public void method(){
     

        System.out.println("父类方法");
    }
    public void methodFu() {
     
        System.out.println("父类特有的方法");
    }
}
public class Zi extends Fu {
     
    @Override
    public void method(){
     
        System.out.println("子类方法");
    }
}
public class Demo01Multi {
     
    public static void main(String[] args) {
     
        //使用多态的写法
        //左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();
        //编译看左(看Fu类中是否有method),运行看右(运行的是Zi类的method)
        obj.method();//子类方法
        obj.methodFu();//父类特有的方法
    }
}

动物的例子

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

    //子类特有方法
    public void catchMouse(){
     
        System.out.println("抓老鼠");
    }
}
public class Dog extends Animal {
     
    @Override
    public void eat(){
     
        System.out.println("骨头");
    }
    public void watchHouse(){
     
        System.out.println("看家");
    }
}
/*
向上转型就是多态的使用,多态就是向上转型

向上转型一定是安全的,但有一个弊端:
对象一旦向上转型为父类,那么就无法调用子类原本特有的内容

解决方案:用对象的向下转型【还原】。
 */
public class Main {
     
    public static void main(String[] args) {
     
        //对象的向上转型,就是:父类引用指向子类对象
        Animal animal = new Cat();
        animal.eat();//猫吃鱼
        //就是.eat()时先看Animal类中是否有eat()方法,
        //有就可以,出来
        //但是用eat()的时候,用的时new出来的对象Cat的方法


        /*animal.catchMouse();//错误写法!*/
        //因为Animal animal = new Cat();是将猫当动物来看的
        //不是所有的动物都有catchMouse()方法


        //向下转型,进行”还原“动作
        Cat cat = (Cat) animal;
        cat.catchMouse();//抓老鼠

        //下面是错误的向下转型
        //本来new的是一只猫,现在非要当狗
        Dog dog = (Dog) animal;//错误写法,编译不会报错,但运行会出现异常
        //ClassCastException
    }
}

Instanceof

/*
如何才能知道一个父类引用的对象,本来是什么子类?
格式:
对象 instanceof 类名称
这将会得到一个boolean值的结果,也就是判断前面的对象能不能当作后面类型的实例
 */
public class Instanceof {
     
    public static void main(String[] args) {
     
        Animal animal = new Dog();
        animal.eat();

        //如果希望调用子类特有的方法,需要向下转型
        //判断一下父类引用animal本来是不是Dog
        if(animal instanceof Dog){
     
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        //判断一下animal本来是不是Cat
        if(animal instanceof Cat){
     
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
        giveMe_A_Pet(new Dog());
    }
    public static void giveMe_A_Pet(Animal animal){
     
        if(animal instanceof Dog){
     
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        //判断一下animal本来是不是Cat
        if(animal instanceof Cat){
     
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}

final关键字

final关键字代表最终、不可改变的。

常见四种用法:

1、可以用来修饰一个类
2、可以用来修饰一个方法
3、还可以用来修饰一个局部变量
4、还可以用来修饰一个成员变量

当final关键字用来修饰一个类的时候,格式:

public final class 类名称{
     
    //...
}

含义

			当前这个类不能有任何的子类
			 即final类不能作为父类。

注意

一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没有儿子。)

当final关键字用来修饰一个方法的时候,格式:

修饰符 final 返回值类型 方法名称(参数列表){
     
    //方法体
}

含义:

这个方法就是最终方法,不能被覆盖重写。

注意:

对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
public class Fu {
     
    public void method(){
     
        System.out.println("父类方法执行");
    }
    public final void methodFinal(){
     
        System.out.println("最终方法,没有办法被子类覆盖重写");
    }
}
public class Zi extends Fu {
     
    @Override
    public void method(){
     
        System.out.println("子类覆盖重写了这个方法");
    }
}


一旦使用final用来修饰局部变量,那么这个变量就不能进行更改。

对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
public class Demo01Final {
     
    public static void main(String[] args) {
     
        //一旦使用final用来修饰局部变量,那么这个变量就不能进行更改。
        final int num = 10;
        //正确写法!只能保证有唯一一次赋值即可
        final int num1;
        num1 = 30;
        //对于基本类型来说,不可变说的是变量当中的数据不可改变
        //对于引用类型来说,不可变说的是变量当中的地址值不可改变
        Student stu = new Student("凡星");
        System.out.println(stu);//@2d98a335(地址值)
        System.out.println(stu.getName());//凡星
        stu = new Student("fx");
        System.out.println(stu);//@16b98e56(地址值)
        System.out.println(stu.getName());//fx
        System.out.println("==========================");
        final Student stu1 = new Student("hh");
        //错误写法,final的引用类型变量,其中的地址不可改变
//        stu1 = new Student("xx");
        stu1.setName("xx");
        stu1.getName();
        System.out.println(stu1.getName());//xx
    }
}

成员变量,如果使用final关键字修饰,那么这个变量也照样是不可变。

1、由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了
2、对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值
3、必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值
/*
一个标准的类,包含以下几个东西
1、私有的成员变量
2、无参构造
3、全参构造
4、getter、setter
以上除1自己写,其他用Alt+Insert快捷键
 */
public class Student {
     
    private final String name = "fx";

Java中的四种权限修饰符

public > protected > (default) > private
同一个类 YES YES YES YES
同一个包 YES YES YES NO
不同包子类 YES YES NO NO
不同包非子类 YES NO NO NO
(1)私有权限 private:private可以修饰数据成员,构造方法,方法成员,不能修饰类(此处指外部类,不考虑内部类)。被private修饰的成员,只能在定义它们的类中使用,在 其他类中不能调用。
(2)默认权限 default:类,数据成员,构造方法,方法成员,都能够使用默认权限,即不写任何关键字。默认权限即同包权限,同包权限的元素只能在定义它们的类中,以及同包 的类中被调用。
(3)受保护权限 protected:protected可以修饰数据成员,构造方法,方法成员,不能修饰类(此处指外部类,不考虑内部类)。被protected修饰的成员,能在定义它们的类中,同包 的类中被调用。如果有不同包的类想调用它们,那么这个类必须是定义它们的类的子类。
(4)公共权限 public:public可以修饰类,数据成员,构造方法,方法成员。被public修饰的成员,可以在任何一个类中被调用,不管同包或不同包,是权限最大的一个修饰符。

注意

(1)并不是每个修饰符都可以修饰类(指外部类),只有public和default可以。
(2)所有修饰符都可以修饰数据成员,方法成员,构造方法。
(3)为了代码安全起见,修饰符不要尽量使用权限大的,而是适用即可。比如,数据成员,如果没有特殊需要,尽可能用private。
(4)修饰符修饰的是“被访问”的权限。

你可能感兴趣的:(JavaSE,java)