final
final(关键字)
1.修饰方法 作用: 被修饰的方法 不能被重写
2.修饰变量 final 修饰引用数据类型时 对象中的成员变量值是可以被修改的
被final修饰的对象 的地址 不能改变(不能重新指向)
3.修饰类 作用 :被修饰的类 不能被继承
例如:
public static void main(String[] args) {
/*
ClassA a = new ClassA();
a.fun();
//final 修饰的基本数据类型的变量 不能被 重新赋值
final int num = 10;
System.out.println(num);
num = 15;
*/
// final 修饰引用数据类型时
// 对象中的成员变量值是可以被修改的
final ClassA a1 = new ClassA();
// 修改成员变量
a1.num = 10;
a1.num = 15;
// 被final修饰的对象 的地址 不能改变(不能重新指向)
//a1 = new ClassA();
System.out.println(a1.num);
}
class ClassA{
// num 创建对象时 有默认的初始值 是0
// 但是这个初始值 是无效的
int num;
public final void fun() {
System.out.println("我是ClassA的fun方法");
}
}
class ClassB extends ClassA{
//被final修饰的方法 不能被重写
// public void fun() {
//
// }
}
final修饰成员变量 该成员变量 必须有 有效的初值(如果你不赋值的话 系统也会给你一个默认值)
(但是这个默认值是无效的)
(所以用final修饰成员变量时 必须要给成员变量赋值)
被final修饰的成员变量 程序中不能被修改 相当于常量
被final修饰的成员变量的使用场景:
一般会与 public static 连用
命名规范:
纯大写 多个单词用下划线分开
例如:
public static void main(String[] args) {
System.out.println(ClassC.MAX_VALUE);
}
class ClassC{
public static final int MAX_VALUE = 10;
}
public void fun(){
System.out.println(MAX_VALUE);
}
这里 打印出来的 是 10;
例如2:
public void fun() {
final int num = 15;//局部变量用final修饰时
num = 15 //这里就会报错 因为用final修饰时
// num的值不能被修改
}
例如3:
public void fun(final int i) {//final修饰参数
i = 15;//这里会报错
//当final修饰参数时
//参数的值也不能被修改
}
多态
多态规则: 一种事物的多种形态
多态前提:
1.类与类之间 要产生联系 继承关系
2.要有方法重写(没有方法重写 多态的意义不大)
3.核心:父类引用指向子类空间(声明方式)
例如:
public class Demo {
public static void main(String[] args) {
//本类的引用指向 本类的对象空间
//Cat cat = new Cat();
//父类的引用 指向 子类的空间
Animal cat = new Cat();
cat.shout();
// 使用多态 来声明子类对象
Animal dog = new Dog();
dog.shout();
}
}
class Animal{
String name;
String kind;
public void shout() {
System.out.println("我是动物叫出声");
}
@Override
public String toString() {
return name + kind;
}
}
class Cat extends Animal{
public void shout() {
System.out.println("我是猫叫喵喵喵");
}
@Override
public String toString() {
return super.toString();
}
}
class Dog extends Animal{
public void shout() {
System.out.println("我是狗叫汪汪汪");
}
@Override
public String toString() {
return super.toString();
}
}
多态调用成员变量
public class Demo{
public static void main(String[] args) {
//多态的形式创建对象
Father f = new Son();
System.out.println(f.num)//这里打印的是10
//当使用父类引用 指向子类空间的时候
//父类的引用 只能访问到
//子类 空间中 属于 父类的那部分(super访问的部分)
//当本类引用指向本类空间的时候
//本类的引用可以访问到 整个 空间
//如果父类中 没有 num 这个变量
//那么就会直接报错
}
}
class Father{
int num = 10;
public void print() {
System.out.println("我是Father类的 print方法");
}
}
class Son extends Father{
int num = 20;
public void print() {
System.out.println("我是Son类的 print方法");
}
}
多态调用成员方法
public class Demo{
public static void main(String[] args) {
//多态的形式创建对象
Father f = new Son();
//f 调用 print 这个方法
f.print()//这里打印的是"我是Son类的print方法"
//因为f是指向 Son()这个地址的
//如果是调用方法 则会使用就近原则
//如果子类中没有这个方法 那么就回去父类中寻找
}
}
class Father{
public void print() {
System.out.println("我是Father类的 print方法");
}
}
class Son extends Father{
int num = 20;
public void print() {
System.out.println("我是Son类的 print方法");
}
}
多态 调用成员变量 和 调用 成员方法 在内存中的表现
举例:
//人 说话(聊天)
//骗子 说话(洗脑) 打人
public class Demo {
public static void main(String[] args) {
//使用多态的形式创建对象
//骗子把自己的逼格升高 伪装成了 一个人
//向上转型
Person p = new Liar();
// 调用子类的方法
p.speak();
// 调用子类特有方法
// 多态下 创建出来的对象
// 是不能直接调用子类的特有方法
// p.hit();
// 需要 把这个对象 进行 向下转型(相当于 强制类型转换)
// 注意: 必须要是这个类型 才能进行强转
// 先有向上转型 才会有 向下转型
Liar liar = (Liar)p;
liar.hit();
//调用重写父类方法 和 子类特有方法
}
}
class Person{
public void speak() {
System.out.println("说话");
}
}
// 骗子类
class Liar extends Person{
public void speak() {
System.out.println("洗脑");
}
public void hit() {
System.out.println("打到死为止");
}
}
多态的优势:
1.代码维护性强(这条建立在 继承的基础上)
2.方法的扩展性强(核心好处)
多态的弊端:
使用多态声明对象的时候 无法直接调用子类的特有方法
只能通过向下转型后 才能使用子类特有的方法
/*
* 需求:
* 武器类 打 挥舞武器
* 刀类 打 挥舞刀 — 砍人
* 练功 练刀
* 棍类 打 挥棍 —— 敲人
* 练棍 耍棍
* main方法 封装一个创建刀的方法 在方法中 调用 挥舞刀方法
*
*/
public class Demo06 {
// 接收的时候 相当于 Weapons weapons = new weapons(); 向上转型
// 这时候 只要是 武器类的 子类 都能使用这个方法
//用这个方法写可以避免 如果很多人都要使用武器
//就不用 创建很多 多态调用方法 可以节省很多代码量
public static void makeWeapons(Weapons weapons) {
weapons.fight();
//判断是不是 刀的类型
//如果是刀 再进行向下转型
//weapons instanceof Broadsword 判断weapons是不是Broadsword
if (weapons instanceof Broadsword) {
//向下转型
Broadsword broadsword = (Broadsword) weapons;
//调用特有的 方法
broadsword.practice();
}
// 判断 是不是 棍
if (weapons instanceof Stick) {
Stick stick = (Stick) weapons;
stick.practice();
}
}
public static void main(String[] args) {
makeWeapons(new Broadsword());
makeWeapons(new Stick());
}
}
class Weapons{
public void fight() {
System.out.println("挥舞武器");
}
}
class Broadsword extends Weapons{
@Override
public void fight() {
System.out.println("砍人");
}
public void practice() {
System.out.println("练屠龙刀 ");
}
}
class Stick extends Weapons{
@Override
public void fight() {
System.out.println("敲人");
}
public void practice() {
System.out.println("练五郎八卦棍");
}
}