final 关键字
final
1.修饰方法 作用 被修饰的方法 不能被重写
2.修饰变量 作用 被final修饰的对象的地址不能改变(不能重新指向)
修饰的基本数据类型的变量不能被重新赋值
3.修饰类 作用 被修饰的类不能被继承
示例代码:
public class Demo01 {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.fun();
// final修饰的基本数据类型的变量 不能被重新赋值
final int num = 10;
System.out.println(num);
// final 修饰 引用数据类型时 对象中成员变量值是可以被修改的
final ClassA a1 = new ClassA();
a1.num = 10;
a1.num = 15;
System.out.println(a1.num);
// 被final 修饰的对象 的地址不能改变(不能重新指向)
//a1 = new ClassA();
}
}
class ClassA{
// num创建对象时 有默认初始值 是0
// 但是这个初始值 是无效的
int num;
public final void fun() {
System.out.println("我是ClassA的fun方法");
}
}
final 修饰 成员变量的时候 该成员变量必须有个有效的初值
例如:final String name = "yy";
被final 修饰的变量 程序中不能被修改 相当于常量
一般会与 public static 连用
常量命名规范:纯大写 多个用下划线分开
例如:public static final int NUM = 10;
参数也可以被final修饰 相当于修饰的是局部变量
多态
多态规则(前提):一种事物的多种形态
1.类与类之间 要产生联系即继承关系
2.要有方法的重写(没有方法的重写,多态的意义不大)
3.核心:父类引用指向子类空间(声明方式)
示例代码:
public class Demo03 {
public static void main(String[] args) {
// 本类的引用指向 本类对象的空间
//Dog dog = new Dog();
// 父类引用指向 子类对象的空间
Animal animal = new Dog();
animal.speak();
// 使用多态来声明子类对象
Animal animal1 = new Cat();
animal1.speak();
}
}
class Animal{
String name;
String type;
public void speak() {
System.out.println("我是动物出声");
}
@Override
public String toString() {
return "姓名:" + name + " 种类:" + type;
}
}
class Dog extends Animal{
@Override
public void speak() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal{
@Override
public void speak() {
System.out.println("喵喵喵");
}
}
调用成员变量和调用成员方法
多态时,调用成员变量 和 调用成员方法
多态 调用成员变量时
Father father = new Son();
简单记: 编译和运行 都看等号左边 左边(父类引用)
当使用父类引用 指向子类空间的时候
父类的引用 只能看见子类空间中 属于 父类的那部分(super 访问的部分)
当本类引用 指向本类空间的时候
本类的引用 可以访问到整个空间
例如:
public class Demo04 {
public static void main(String[] args) {
Father father = new Son();
System.out.println(father.num);
/* 动态绑定
* 编译时: 寻找父类中有没有该方法(看等号的左边)
* 运行时: 调用的是子类中重写的方法
*
* 简单记(编译看左边(父类) 运行看右边(子类))
*/
father.print();
Son son = new Son();
System.out.println(son.num);
son.print();
}
}
class Father{
int num = 10;
public void print() {
System.out.println("我是 Father类的print 方法");
}
}
class Son extends Father{
int num = 20;
@Override
public void print() {
System.out.println("我是Son类的print方法");
}
}
多态好处与弊端
多态的好处:
1.代码维护性强(这条建立在 继承的基础上)
2.方法的扩展性强(核心好处)
扩展性强代码举例:
public class Demo06 {
// 封装一个方法创建刀
// 接收的时候 相当于 WQ wq = new Dao(); 向上转型
// 这时候 只要是武器类的子类 都能使用这个方法
public static void createWQ(WQ wq) {
wq.hit();
// 判断一下 是不是 刀类型
// 如果是刀 再进行向下转型
// wq instanceof Dao 判断wq 是否是Dao类型
if (wq instanceof Dao) {
// 向下转型
Dao dao = (Dao)wq;
// 调用特有的方法
dao.lianDao();
}
// 判断是不是棍
if (wq instanceof Gun) {
Gun gun = (Gun)wq;
gun.lianGun();
}
}
public static void main(String[] args) {
// 使用该方法
createWQ(new Dao());
createWQ(new Gun());
}
}
class WQ{
public void hit() {
System.out.println("挥舞武器");
}
}
class Dao extends WQ{
@Override
public void hit() {
System.out.println("挥舞刀 砍人");
}
// 练刀
public void lianDao() {
System.out.println("练刀");
}
}
class Gun extends WQ{
@Override
public void hit() {
System.out.println("挥棍 敲人");
}
public void lianGun() {
System.out.println("练棍");
}
}
多态的弊端:
使用多态声明对象的时候无法直接调用子类的特有方法,只能通过向下转型后才能使用子类特有的方法
弊端代码举例:
public class Demo05 {
public static void main(String[] args) {
// 骗子把自己的逼格升高了 伪装成了一个人
// 向上转型
Person person = new PZ();
// 调用重写方法
person.speak();
// 调用子类特有方法
// 多态下 创建出来的对象 是不能直接调用子类的特有方法
// person.hit();
//需要把这个对象 进行向下转型(相当于强制类型转换)
// 注意: 必须要是这个类型 才能进行强转
// 先有向上转型 才会有向下转型
PZ pz = (PZ)person;
pz.hit();
}
}
class Person{
public void speak() {
System.out.println("聊天侃大山");
}
}
// 骗子类
class PZ extends Person{
@Override
public void speak() {
System.out.println("洗脑");
}
public void hit() {
System.out.println("打到死为止");
}
}