04java基础课堂笔记 - 面向对象课时2-关键字super this instanceof static final
p69 super详解
1.1 this和super
- super不是引用,也不保存内存地址,super也不指向任何对象
- super只代表当前对象内部的那一块父类型的特征
- this代表当前对象,可以独立使用被直接调用,而super不支持单独使用,后面必须有点
1.2、super() 表示通过子类的构造方法调用父类的构造方法,模拟现实世界的这种场景:要想有儿子,需要先有父亲
- 在子类所有的构造方法中都有一个隐藏代码“super(); ”,默认调用父类的无参构造,因此建议显示定义父类的无参构造,保证父类的无参构造存在
- 也可以显示编辑“super(实参)”语句,调用父类的有参构造
- this()和super()不能共存,因为它们都必须是构造方法的第一行
- 子类构造方法执行时必然调用父类构造方法,但无论new什么对象,父类的构造方法一定会执行,最后老祖宗类Object类的无参构造方法一定会执行,而且Object类的无参构造处于栈顶,最后调用最先执行结束
2.1、super可以用在实例方法中和构造方法中
- super语法是“super.”、“super()”
- super不能使用在静态方法中
- super.大部分情况下可以省略,什么时候不能省略呢?
- super()这种语法只能出现在构造方法的第一行,表示在子类的构造方法中调用“父类”中的构造方法,目的是创建子类对象时,先初始化父类型特征
2.2、访问父类特征的数据的语法:
super. 属性名
super. 方法名(实参列表);
2.3、用在构造方法中调用父类的构造方法:
super();
super(实参列表);
2.4、super.大部分情况下可以省略,什么时候不能省略呢?
当子类和父类中有同名属性,或者有相同的方法(方法覆盖)时,如果想在子类中访问父类特征的数据,那么必须使用“super.”加以区分
java允许在子类中出现父类的同名变量/同名方法,那么怎么区分呢?
this.name 访问当前对象的name属性
super.name 访问当前对象的父类特征中的name属性
this.move(); 访问当前对象的move()方法,重写的方法
super.move(); 访问父类中的move()方法
4.1、注意:
在构造方法执行过程中,一连串的调用了父类的构造方法,父类的构造方法又继续向上调用它的父类的构造方法,但是实际上只创建了一个对象
4.2、思考:super(实参)真是的作用是什么?
初始化当前对象的父类型特征,并不是创建新对象,实际上对象只创建了一个
4.3、super的真正意义是什么?
super关键字代表的是当前对象的那部分父类型特征
示例1:super()的作用

public class Test{ public static void main(String[] args){ //1 4 3 new B(); } } class A extends Object{ public A(){ //默认代码,调用父类的构造方法 //super(); System.out.println("1 A类的无参构造方法!"); } public A(int i){ //super(); System.out.println("2 A类的有参构造方法!"); } } class B extends A{ public B(){ //使用this()调用当前类的有参构造,此时super()消失 this("zhangsan"); System.out.println("3 B类的无参构造方法!"); } public B(String name){ //super(); System.out.println("4 B类的有参构造方法!"); } }
示例2:判断程序的输出结果

public class Test{ public static void main(String[] args){ //1 3 7 6 5 new C(); } } class A extends Object{ public A(){ System.out.println("1-A类的无参构造执行!"); } public A(int i){ System.out.println("2-A类的有参构造执行!"); } } class B extends A{ public B(){ System.out.println("3-B类的无参构造执行!"); } public B(String name){ System.out.println("4-B类的有参构造执行(String)"); } } class C extends B{ public C(){ this("zhangsan"); System.out.println("5-C类的无参构造执行!"); } public C(String name){ this("zhangsan",20); System.out.println("6-C类的有参构造执行(String)"); } public C(String name,int age){ System.out.println("7-C类的有参构造执行(String,int)"); } }
示例3:在恰当的时间使用:super(实参列表)

public class Test{ public static void main(String[] args){ CreditAccount ca1 = new CreditAccount(); System.out.println(ca1.getActno() + "," + ca1.getBalance() + "," + ca1.getCredit()); CreditAccount ca2 = new CreditAccount("11111",10000.0,0.999); System.out.println(ca2.getActno() + "," + ca2.getBalance() + "," + ca2.getCredit()); } } //账户 class Account extends Object{ private String actno; private double balance; public Account(){ //super(); //this.actno = null; //this.balance = 0.0; } public Account(String actno,double balance){ this.actno = actno; this.balance = balance; } //get/set public void setActno(String actno){ this.actno = actno; } public String getActno(){ return actno; } public void setBalance(double balance){ this.balance = balance; } public double getBalance(){ return balance; } } //信用卡 class CreditAccount extends Account{ private double credit; public CreditAccount(){ //super(); //this.credit = 0.0; } public CreditAccount(String actno,double balance,double credit){ /*私有属性只能在本类中访问 this.actno = actno; this.balance = balance; */ //以上两行代码在恰当的位置,正好可以使用:super(actno,balance); //通过子类的构造方法调用父类的构造方法 super(actno,balance); this.credit = credit; } public void setCredit(double credit){ this.credit = credit; } public double getCredit(){ return credit; } }
示例4:super() ruper. this.的使用以及不能省略情况

public class Test{ public static void main(String[] args){ Vip v = new Vip("张三"); v.shopping(); } } //客户 class Customer{ String name; public Customer(){} public Customer(String name){ super(); this.name = name; } } class Vip extends Customer{ //重定义属性代表子类的独立特征 //String name; public Vip(){} public Vip(String name){ //调用父类的有参构造 super(name); } public void shopping(){ System.out.println(this.name + "正在购物!"); //super.表示当前对象的父类特征,是当前对象中的一块空间 System.out.println(super.name + "正在购物!"); System.out.println(name + "正在购物!"); } }
示例5:super不是引用

/*测试结论: super不是引用,也不保存内存地址,super也不指向任何对象 super只代表当前对象内部的那一块父类型的特征 */ public class Test{ public static void main(String[] args){ Test t = new Test(); t.dosome(); } public void dosome(){ //输出“引用”的时候,会自动调用引用的toString()方法 //System.out.println(this.toString()); System.out.println(this); //编译错误,需要‘.’ //System.out.println(super); } }
示例6:super也可以访问方法

public class Test{ public static void main(String[] args){ Cat c = new Cat(); c.yidong(); } } class Animal{ public void move(){ System.out.println("Animal move!"); } } class Cat extends Animal{ @Override public void move(){ System.out.println("Cat move!"); } public void yidong(){ this.move(); move(); //super不仅可以访问属性,也可以访问方法 super.move(); } }
p70、this 详解
1、this在内存方面的特点综述:
- this是一个变量,是一个引用,this保存当前对象的内存地址,指向对象自身,代表“当前对象”
- 一个对象一个this,this存储在堆内存中对象的内部
- this可以用在实例方法中,也可以用在构造方法中
- 语法是“this”、“this.”、“this()”
- this.大部分情况下可以省略,但是用来区分实例变量和局部变量的时候不能省略
- this不能使用在静态方法中
- this()这种语法只能出现在构造方法的第一行,表示当前构造方法调用本类中的其它构造方法,目的是代码复用
1)、this可以用在实例方法中代表当前对象
- 谁(对象)调用这个实例方法,this就是谁
- this可以调用本类的属性,也可以调用本类的其它方法
- 表达式格式:
this.属性名
this.方法名(实参列表)
2)、“this.”大部分情况下是可以省略的,什么时候不能省略呢?
- 在实例方法中或者构造方法中,为了区分实例变量和局部变量,这种情况下this是不能省略的
如:public void setName(String name){
this.name = name;
}
3)、为什么this不能在静态方法中使用呢?
- 因为this代表当前对象,静态方法中不存在当前对象
2、this还可以用在构造方法中
2.1、在当前的构造方法中使用this()语句调用本类的另一个构造方法,
语法格式:
this();
this(实参列表);
- 通过构造方法1去调用构造方法2,可以做到代码复用
- 需要注意点是:两个构造方法必须是在同一个类当中
2.2、this()语句只能出现在构造方法的第一行,因此一个构造方法中只能有一个this()语句
示例1:this的应用

public class Test{ public static void main(String[] args){ Customer c1 = new Customer("张三"); c1.shopping(); Customer c2 = new Customer("李四"); c2.shopping(); Customer.doSome(); } } class Customer{ //实例变量 String name; //构造方法 public Customer(){} public Customer(String s){ name = s; } //实例方法 public void shopping(){ //这里this是当前对象,this可以省略 //c1调用shopping(),this就是c1,c2调用shopping(),this就是c2 System.out.println(this.name + "正在购物!"); System.out.println(name + "正在购物!"); } //静态方法 public static void doSome(){ //this代表当前对象,而静态方法的调用不需要对象,矛盾了 //错误:无法从静态上下文中引用非静态 变量 this //System.out.println(this.name); //创建对象访问实例变量 Customer c = new Customer(); System.out.println(c.name); } }
示例2:this不能省略的用法

public class Test{ public static void main(String[] args){ Student s = new Student(); s.setId(111); s.setName("张三"); System.out.println("学号:" + s.getId()); System.out.println("姓名:" + s.getName()); Student s2 = new Student(222,"李四"); System.out.println("学号:" + s2.getId()); System.out.println("姓名:" + s2.getName()); } } class Student{ //学号 private int id; //姓名 private String name; //构造方法 public Student(){} //使用见名知义形参,增强了程序的可读性 public Student(int id,String name){ this.id = id; this.name = name; } //get、set方法 /* public void setId(int id){ //就近原则,这两个id都是局部变量id,和实例变量id没关系,因此this不能省略 id = id; } */ public void setId(int id){ //id是局部变量,this.id是实例变量 //this.的作用是区分局部变量和实例变量 this.id = id; } public int getId(){ //teturn this.name; getId实际上获取的是当前对象的id, //严格来说,这里是有一个this.的,但是这个this可以省略 return id; } /* public void setName(String name){ //就近原则,这两个name都是局部变量name,和实例变量name没关系,因此this不能省略 name = name; } */ public void setName(String name){ this.name = name; } public String getName(){ return name; } }
示例3:this()语法用在构造方法中

public class Test{ public static void main(String[] args){ Date d1 = new Date(); d1.detail(); Date d2 = new Date(2008,8,8); d2.detail(); } } /*需求: 1、定义一个日期类,可以表示年月日信息 2、需求中要求: 如果调用无参构造方法,默认创建的日期为:1970年1月1日 当然除了调用无参构造方法之外,也可以调用有参的构造方法来创建日期对象 */ class Date{ //年 private int year; //月 private int month; //日 private int day; //无参构造方法 //初始化值是固定值 public Date(){ /* this.year = 1970; this.month = 1; this.day = 1; */ //当前构造方法使用this()语法调用另一个构造方法,实现代码复用 this(1970,1,1); } //有参构造方法 public Date(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } //提供一个可以打印日期的方法 public void detail(){ System.out.println(this.year + "年" + this.month + "月" + this.day + "日"); } //get/set方法 public void setYear(int year){ this.year = year; } public int getYear(){ return year; } public void setMonth(int month){ this.month = month; } public int getMonth(){ return month; } public void setDay(int day){ this.day = day; } public int getDay(){ return day; } }
示例4:一个综合性的练习题

//一个综合性的测试 public class Test{ //实例变量 int i = 10; //静态方法 public static void dosome(){ System.out.println("do some!"); } //实例方法 public void doOther(){ System.out.println("do other!"); } //静态方法 public static void method1(){ //调用doSome //使用完整方式调用 Test.dosome(); //使用省略方式调用 dosome(); //调用doOther //使用完整方式调用 Test t = new Test(); t.doOther(); //不能使用省略方式调用 //访问i //完整方式访问 System.out.println(t.i); //不能使用省略方式访问 } //实例方法 public void mathod2(){ //调用doSome //使用完整方式调用 Test.dosome(); //使用省略方式调用 dosome(); //调用doOther //使用完整方式调用 this.doOther(); //使用省略方式调用 doOther(); //访问i //完整方式访问 System.out.println(this.i); //省略方式访问 System.out.println(i); } //主方法 public static void main(String[] args){ //要求在这里编写程序调用method1 //使用完整方式调用 Test.method1(); //使用省略方式调用 method1(); //要求在这里编写程序调用method2 //使用完整方式调用 Test t = new Test(); t.method2(); //不能使用省略方式调用 } }
p72 instanceof 运算符(参考多态章节)
1.1、instanceof 的意义
- instanceof 用于在运行阶段动态判断引用指向的对象是否属于目标类型
- instanceof 是一个逻辑运算符,运算符的结果是一个布尔值:true/false
1.2、instanceof 的语法机制
- 首先编译阶段编译器只检查语法,检查左侧的引用的类型与右侧的目标类型是否相同,或者存在继承关系,是则编译通过,否则编译错误
- 然后运行阶段进行判断运算instanceof运算,判断左侧的引用指向的对象是否属于目标类型,是则返回true,否则返回false
- 表达式语法:
(引用/对象 instanceof 类型名)
if(引用/对象 instanceof 类型名){ 将引用向下转型 }
如:Animal a = new Cat(); 【Animal a = new Bird(); 】 Bird b = (Bird)a;
欲向下转型为Bird要先进行判断:(a instanceof Bird)
编译阶段:先检查引用a的类型是Animal类型,与目标类型Bird存在继承关系,所以编译通过。
运行阶段:再进行判断运算,即读作a是一个Bird吗?a的对象是一个Bird类的实例吗?a的对象是Bird类型吗?是则返回true,否则返回false
1.2、instanceof 的作用
instanceof 只用于引用类型向下转型的判断运算,用来规避类型转换异常ClassCastException,不能用于基本数据类型
示例1:instanceof的使用

/*明明可以观察到底层对象到底是new Bird()还是new Cat() 为什么要进行instanceof的判断呢?? 原因是:以后可能直接看不到了 */ public class Test{ public static void main(String[] args){ Animal x = new Cat(); Animal y = new Bird(); /*错误:java.lang.ClassCastException: Cat cannot be cast to Bird Bird b = (Bird)x; b.sing();*/ if(x instanceof Cat){ Cat c = (Cat)x; c.catchMouse(); }else if(x instanceof Bird){ Bird b = (Bird)x; b.sing(); } if(y instanceof Cat){ Cat c = (Cat)y; c.catchMouse(); }else if(y instanceof Bird){ Bird b = (Bird)y; b.sing(); } } } class Animal{ public void move(){ System.out.println("动物在移动!!!"); } } class Cat extends Animal{ @Override public void move(){ System.out.println("cat走猫步!!!"); } public void catchMouse(){ System.out.println("cat正在抓老鼠!!!"); } } class Bird extends Animal{ @Override public void move(){ System.out.println("bird在飞翔!!!"); } public void sing(){ System.out.println("bird在唱歌!!!"); } }
示例2:看不到真实的底层对象 向下转型须进行instanceof的判断

//直接看不到底层对象时,需要进行instanceof的判断 public class Test{ public static void main(String[] args){ //main方法是程序员A负责编写 AnimalTest at = new AnimalTest(); at.test(new Cat()); at.test(new Bird()); } } class AnimalTest{ /*test方法是程序员B负责编写 test方法的参数是一个Animal 此方法别人会拿去调用,调用时可能给test()方法传递一个Bird,也可能传递一个Cat 对我来说,我不知道test()方法被调用时传过来的是什么 */ public void test(Animal x){ if(x instanceof Cat){ Cat c = (Cat)x; c.catchMouse(); }else if(x instanceof Bird){ Bird b = (Bird)x; b.sing(); } } } class Animal{ public void move(){ System.out.println("动物在移动!!!"); } } class Cat extends Animal{ @Override public void move(){ System.out.println("cat走猫步!!!"); } public void catchMouse(){ System.out.println("cat正在抓老鼠!!!"); } } class Bird extends Animal{ @Override public void move(){ System.out.println("bird在飞翔!!!"); } public void sing(){ System.out.println("bird在唱歌!!!"); } }
示例3:instanceof的语法机制

public class Test{ public static void main(String[] args){ //Object > String //Object > Person > Teacher //Object > Person > Student Student s1 = new Student(); Person s2 = new Student(); Object s3 = new Student(); //测试instanceof运算符的用法 System.out.println(s1 instanceof Student); //true System.out.println(s1 instanceof Person); //true System.out.println(s1 instanceof Object); //true //System.out.println(s1 instanceof Teacher); //编译错误 //System.out.println(s1 instanceof String); //编译错误 System.out.println(s2 instanceof Student); //true System.out.println(s2 instanceof Person); //true System.out.println(s2 instanceof Object); //true System.out.println(s2 instanceof Teacher); //false //System.out.println(s2 instanceof String); //编译错误 System.out.println(s3 instanceof Student); //true System.out.println(s3 instanceof Person); //true System.out.println(s3 instanceof Object); //true System.out.println(s3 instanceof Teacher); //false System.out.println(s3 instanceof String); //false System.out.println(new Student() instanceof Student); //true System.out.println(new Student() instanceof Person); //true System.out.println(new Student() instanceof Object); //true //System.out.println(new Student() instanceof Teacher); //编译错误 //System.out.println(new Student() instanceof String); //编译错误 } } class Person{} class Student extends Person{} class Teacher extends Person{}
p73 static 关键字
1、static 翻译为静态的,是用来修饰方法或属性的
* 静态变量在类加载的时候初始化,内存在方法区内存中开辟,因此访问静态变量不需要创建对象,直接使用类名访问
* 所有static修饰的元素都称为静态的,都是通过“类名.”访问
* 所有static修饰的元素都是类级别的,是类的模板特征,和具体的对象无关
1)什么时候成员变量声明为静态变量/静态方法呢?
- 对于这个类型的所有对象,当某个属性的值都是一样的,不因对象不同而不同,建议定义为类级别特征,定义为静态变量,在方法区中只保留一份,节省内存的开销
- 方法描述的是行为/动作,当所有的对象执行这个行为/动作,产生的结果是一样的时候,那么这个动作已经不在属于具体对象的动作了,可以将这个动作提升为类级别的动作模板级别的动作
2)什么时候成员变量声明为实例变量/实例方法呢?
- 对于这个类型的所有对象,不同的对象其属性的具体值不同,那么该属性须定义为实例变量
- 当执行一个行为/动作过程中,如果该行为需要对象去触发,不同对象执行的结果是不一样的,那么该方法定义为“实例方法”
- 如果中一个方法中直接访问了实例变量,那么该方法也必须是实例方法
3)如何访问静态的与实例的变量/方法?
- 所有静态相关的都是通过“类名.”访问,如果是在同一个类中“类名.”可以省略
- 所有实例相关的都需要先创建对象,采用“引用.”或“this.”的方式访问,如果是在同一个类中“this.”可以省略
4)详解编译错误:无法从静态上下文中引用非静态的变量/方法
- 从静态上下文中只能访问静态相关的东西,并且只能通过“类名.”访问
- 在静态方法中,不能直接访问实例的,必须先new对象,使用“引用.”访问,也不能使用this引用,因为静态方法中没有this
- 从非静态上下文中既可以访问静态相关的,也可以访问实例相关的
- 在实例方法中,访问静态相关的可以采用“类名.”的方式访问,也可以采用“引用.”的方式访问,但实际执行的过程还是类名访问
- 在实例方法中,访问实例相关的只能采用“引用.”的方式访问
4、静态导入包
- 用静态的办法导入包中类的方法,就可直接调用该类的方法或常量
如:import static java.lang.Math.*;
//示例10-1:static 的用法测试

//static 的用法测试 public class Student{ private static int age; //静态变量 private double score; //非静态变量 public void run(){ System.out.println("run"); } public static void go(){ System.out.println("go"); } public static void main(String[] args){ Student s1 = new Student(); //静态变量可以通过类访问,也可以通过对象访问 //静态变量属于当前类时甚至可以直接访问 //非静态变量只能通过对象访问 System.out.println(Student.age); System.out.println(s1.age); System.out.println(age); System.out.println(this.age); System.out.println(s1.score); //方法的调用同理 s1.run(); Student.go(); s1.go(); go(); this.run(); } }
//示例10-3:静态导入包的测试

//Math类的方法都是静态的,可以通过类调用,不用导入包, //import java.lang.Math; public class T10{ public static void main(String[] args){ //输出一个随机数 System.out.println(Math.random()); System.out.println(Math.PI); } } //静态导入包 //Math类里的方法可以用static的办法导入,然后就能直接调用 import static java.lang.Math.*; public class T11{ public static void main(String[] args){ //输出一个随机数 System.out.println(random()); System.out.println(PI); } }
//示例10-4:static的用法,private的用法,get/set的用法,全局变量的使用

public class Applecation{ public static void main(String[] args){ Student s1 = new Student(); //静态变量可以通过类访问,也可以通过对象访问 //非静态变量只能通过对象访问 Student.name = "小强"; s1.sex = true; System.out.println(Student.name);//System.out.println(s1.name); System.out.println(s1.sex); //Student.sex = true; //编译报错 //System.out.println(Student.sex); //编译报错 //静态的方法,可以通过类调用,也可以通过对象调用 //非静态的方法只能通过对象调用 Student.go();//s1.go(); s1.run(); //Student.run(); //编译报错 //private属性私有,必须通过get/set入口访问 //Student.age = 15; //private 访问控制 //s1.score = 87.5; //private 访问控制 //System.out.println(Student.age); //private 访问控制 //System.out.println(s1.score); //private 访问控制 //静态的get/set方法,可以通过类调用,也可以通过对象调用 Student.setAge(13); System.out.println("学生的虚岁年龄是:" + s1.getAge()); //非静态的get/set方法只能通过对象调用 s1.setScore(87.5); System.out.println("加分后:" + s1.getScore()); } } public class Student{ public static String name; //静态变量 public boolean sex; //非静态变量 private static int age; //静态变量 private double score; //非静态变量 //当前类的成员变量都是全局变量,一般可以直接调用 //- 从静态上下文中只能引用静态的变量,不能引用非静态的变量 //- 从非静态上下文中既可以引用静态变量,也可以引用非静态变量 //- 在静态上下文中,静态变量可以使用类引用,不能使用this引用 //- 在非静态上下文中,静态变量既可以使用类引用,也可以使用this引用 //- 非静态变量可以使用this引用,却不能使用类引用 //静态方法 public static void go(){ name = "小明"; // 或者Student.name = "小明"; age = 11; // 或者Student.age = 11; //sex = true; //编译错误 //score = 67.5; //编译错误 System.out.println("go方法执行了," + name + age); //System.out.println(sex + score);//编译错误 } //非静态方法 public void run(){ name = "小花"; //或者Student.name = "小明";this.name = "小明"; age = 12; //或者Student.age = 11;this.age = 11; sex = false; //this.sex = false; score = 77.5; //this.score = 86.5; System.out.println("run方法执行了," + name + sex + age + score); } //private修饰的数据只能在当前类中访问 //为外部程序提供get/set入口 public static int getAge() { age++; return age; } public static void setAge(int ag) { Student.age = ag; System.out.println(name + "设定的年龄是:" + age); } public double getScore() { score++; return score; } public void setScore(double scr) { this.score = scr; System.out.println("输入的成绩是:" + score); } }
155、final 关键字
1、final 表示最终的最后的,不可变的
2、final可以修饰变量、方法、类等
1)final修饰的类无法被继承
如果你不希望该类被继承扩展,就可以给该类加final修饰,从而不扩展子类,如:pubic final class person{}
2)ifnal修饰的方法无法被覆盖被重写,
父类的方法使用final修饰才有意义,可以继承
3)final修饰的变量只能赋值一次,无法修改,一旦赋值不能重新赋值
3.1)final修饰的局部变量,只能赋值一次
3.2)final修饰的实例变量,必须手动初始化,不能采用系统默认值
由于实例变量如果没有手动赋值的话,系统会赋默认值,而final修饰的实例变量一旦赋值将无法修改,因此为了有效初始化,sun公司决定,系统不负责赋默认值,要求程序员必须手动赋值
手动为变量赋值,可以在声明表达式右侧赋值,也可以在构造方法中赋值
3.3)final修饰的实例变量一般要添加static修饰,static final 联合修饰的变量称为“常量”
常量名的字母全部大写,单词之间使用下划线连接
实例变量既然已经使用了final修饰,说明该变量的值不会因对象不同而变化,因此该实例变量应该添加static修饰,变为静态的
常量和静态变量一样,存储在方法区,都是在类加载时初始化,区别是常量的值不变,因此常量一般是公共的public的
* 常量的语法结构:
public static final 类型 常量名 = 值;
public static final double PI = 3.14159265358979;
3.4)final修饰的引用,引用指向的对象无法修改,不能重新指向其它对象,但是对象内部的数据是可以修改的
在当前方法执行过程中,引用指向的对象不能被垃圾回收器回收,直到该方法执行结束后才会释放空间
即使引用赋空值null时同样不可修改
3、总结:
1)final修饰的类无法被继承
2)ifnal修饰的方法无法被覆盖被重写,
3)final修饰的变量只能赋值一次,无法修改
4)final修饰的实例变量,必须手动初始化
5)final修饰的实例变量一般要添加static修饰,static final 联合修饰的变量称为“常量”
6)final修饰的引用,引用指向的对象无法修改,但是对象内部的数据是可以修改的
示例1:常量、static、PI

public class Test{ public static void main(String[] args){ System.out.println(Chinese.COUNTRY); System.out.println("圆周率:" + MyMath.PI); } } class MyMath{ public static final double PI = 3.14159265358979; } class Chinese{ //每一个中国人的国籍都是中国,而国籍不会发生改变,为了防止国籍被修改,建议加final修饰 public static final String COUNTRY = "中国";
补充知识:
1、replaceAll("A","B")
:字符串替换,将字符串对象中的原字符串A全部替换为B,并返回一个新字符串对象,replaceAll(String regex,String replacement){},
String newString = 字符串对象. replaceAll("原字符串", "新字符串")
//示例:字符串替换方法:replaceAll()

public class Replace{ //将所有的"a"字符串替换为"x" public static void main(String[] args){ String newString = "adfjlsdvncxoauweoas".replaceAll("a","x"); System.out.println(newString); } }
2、Date类
import java.util.Date;
new Date(); //返回系统当前时间
示例:读取系统当前时间

import java.util.Date; public class Test{ public static void main(String[] args){ Date date = new Date(); System.out.println("当前时间为:" + date); } }
//即使再小的帆也能远航2021-11-09