目录
super关键字
1.访问父类成员变量
2.调用父类成员方法
class Animal{
//方便后续操作,把成员变量都设置成public
public String name;
public int age;
public void eat(){
System.out.println(name+"吃饭");
}
}
class Dog extends Animal{
public boolean loyal;
//通过构造方法初始化
public Dog(){
//通过super关键字对父类当中的成员变量赋值
super.name = "旺财";
super.age = 4;
super.eat();
//通过this关键字对子类当中的成员变量赋值
this.loyal = true;
}
public void gradHouse(){
System.out.println(name+"守护房子!");
}
}
class Cat extends Animal{
public boolean lazy;
public Cat(){
super.name = "咪咪";
super.age = 3;
super.eat();
this.lazy = false;
}
public void catchMouse(){
System.out.println(name+"抓老鼠!");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.gradHouse();
Cat cat = new Cat();
cat.catchMouse();
}
}
注:在子类方法中或者通过子类对象访问成员时:
1.若是父类和子类中没有相同的成员变量、方法,此时想访问哪个变量就访问哪个变量,也不需要加super关键字。
2.若是父类和子类中有相同的成员变量,此时访问名字相同的变量时,不用super关键字,优先访问子类中变量。
3.若是方法名相同,但是返回值与参数不同,则会匹配到子类或父类中与之对应的方法,若方法名,返回值与参数都相同,优先访问子类中的方法。
4.相同时,非要访问父类中的成员,通过super关键字就可以了。
3.super()调用父类构造方法
class Animal{
//方便后续操作,把成员变量都设置成public
public String name;
public int age;
//自己写的父类构造方法
public Animal(String name,int age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name+"吃饭");
}
}
class Dog extends Animal{
public boolean loyal;
public Dog() {
//通过 super() 调用父类的构造方法
super("旺财", 4);
}
public void gradHouse(){
System.out.println(name+"守护房子!");
}
}
class Cat extends Animal{
public boolean lazy;
public Cat(){
super("咪咪",4);
}
public void catchMouse(){
System.out.println(name+"抓老鼠!");
}
}
注:
1.super关键字只能在非静态的方法中使用。
2.在构造方法调用时,super()和this()不能同时出现。
3.构造方法中一定会有super()的调用,即使没有写上去,编译器也会默认加上去的。在构造方法中详解。
构造方法
1.没有写子类构造方法和父类构造方法
class Father{
int date1;
public void func1(){
System.out.println("这是父类的一个成员方法!");
}
}
class Son extends Father{
int date2;
public void func2(){
System.out.println("这是子类的一个成员方法!");
}
}
public class Test {
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
f.func1();
s.func2();
}
}
虽然在父类和子类中都没有构造方法,但是编译器会自动帮我们把父类和子类的构造方法(不带任何参数的)写上去,并且在子类的构造方法中的第一行调用 super() 。
2.写了子类构造方法,父类没有写
class Father{
int date1;
public void func1(){
System.out.println("这是父类的一个成员方法!");
}
}
class Son extends Father{
int date2;
public Son(){
//super()
//由于父类中没有写构造方法,编译器在父类自动生成不带参数的构造方法
//所以这个super() 虽然没有写,但是编译器一定会在子类构造方法第一行帮我们写上去
System.out.println("这是子类的一个构造方法!");
}
public void func2(){
System.out.println("这是子类的一个成员方法!");
}
}
public class Test {
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
f.func1();
s.func2();
}
}
3.子类和父类中都写了构造方法
class Father{
int date1;
public Father(int n){
System.out.println("这是带一个参数的父类构造方法!");
}
public void func1(){
System.out.println("这是父类的一个成员方法!");
}
}
class Son extends Father{
int date2;
public Son(){
//此时的super必须写上去,并且要把参数对应上
super(66);
System.out.println("这是子类的一个构造方法!");
}
public void func2(){
System.out.println("这是子类的一个成员方法!");
}
}
public class Test {
public static void main(String[] args) {
Father f = new Father(66);
Son s = new Son();
f.func1();
s.func2();
}
}
代码块执行顺序
class People{
public String name;
int age;
public People(){
name = "张三";
age = 18;
System.out.println("这是父类中的一个构造方法在初始化");
}
{
System.out.println("这是父类实例化代码块!");
}
static {
System.out.println("这是父类静态代码块!");
}
public void A(){
System.out.println("这是父类中的一个成员方法!");
}
}
class Student extends People{
String num;
public Student(){
num = "20220809";
System.out.println("这是子类中的一个构造方法在初始化");
}
{
System.out.println("这是子类实例化代码块!");
}
static {
System.out.println("这是子类静态代码块!");
}
public void B(){
System.out.println("这是子类中的一个成员方法!");
}
}
public class Test2 {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("--------------------------------");
Student s2 = new Student();
}
}
小结:
1.静态代码块先执行,并且只执行一次。因为被static修饰的代码块是在类加载阶段执行。
2.先执行父类代码,再执行子类代码。其中实例代码块比构造方法要先被执行。这是在实例化对象的时候执行的。
final关键字
1.修饰成员变量
表示该变量就是常量,不能被修改。
final int a = 10;
//a不能被修改
//a = 20;
2.修饰成员方法
表示该方法不能被 重写。
多态的文章当中讲解 重写。
3.修饰类
表示该类不能被继承
final public class Animal {
//无法继承此类
}
public class Cat extends Animal {
//编译会出错
}
有什么错误评论区指出。