一、super关键字
Super关键字的作用:在子类方法中访问父类的成员。
//Father.java
public class Father {
int a = 20;
int b = 30;
public void method1(){
System.out.println("Father.method1");
}
}
//Son.java
public class Son extends Father{
int a = 10;
char b = 'b';
//同名,相同参数列表
public void method1(){
System.out.println("Son.method1");
}
public void method2(){
//直接访问只能访问到子类的成员变量
System.out.println("a = " + a);
System.out.println("b = " + b);
//使用super访问到父类中的成员变量
System.out.println("super.a = " + super.a);
System.out.println("super.b = " + super.b);
method1(); //直接访问只能访问到子类
super.method1(); //使用super关键字进行访问
}
public static void main(String[] args) {
Son son = new Son();
son.method2();
}
}
super和this的异同
相同:
- 都是java的关键字
- 都只能在非静态方法中使用,用来访问非静态成员方法和字段。
- 都在构造方法中调用,都必须是构造方法的第一条语句(不能同时存在)
不同:
this
是当前对象的引用,super
是父类对象的引用。- 非静态成员方法中,
this
是用来访问本类的方法和属性,super
用来访问父类继承下来的方法和属性。 this
是非静态成员方法的一个隐藏参数,super
不是隐藏参数。- 成员方法访问成员时,编译过后会将
this
还原,通过this
来进行访问。使用super
访问父类成员,编译之后在字节码层面是不存在super
的。
- 在构造方法中,
this
调用本类构造方法,super
用于调用父类构造方法,两种不能同时存在。 - 构造方法中一定会存在
super
调用,编译器会自动增加,但this
没写则没有。
二、protected关键字
范围 | private | default | protected | public |
---|---|---|---|---|
同一个包中的同一个类 | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
同一个包中的不同类 | 可以访问 | 可以访问 | 可以访问 | |
不同包中的子类 | 可以访问 | 可以访问 | ||
不同包中的非子类 | 可以访问 |
包的结构,通过下面的例子来介绍protected
关键字:
public class A {
private int a;
protected int b;
public int c;
int d;
}
//在相同包的子类中
public class AA extends A{
public void method(){
//super.a = 10; // 父类的private成员不可见
super.b = 20; // 父类的protected成员可以访问
super.c = 30; // 父类中public成员可以访问
super.d = 40; // 父类default成员可以访问
}
}
//不同包的子类
public class B extends A {
public void method(){
//super.a = 10; //父类的private成员不可见
super.b = 20; //父类protected成员可以访问
super.c = 30; //父类public成员可以访问
//super.d = 40; //父类default成员不能直接
}
}
//不同包中的类
public class TestB {
public static void main(String[] args) {
B b = new B();
b.method();
//System.out.println(b.a); //父类的private成员不可见
//System.out.println(b.b); //父类的protected成员不能直接访问
System.out.println(b.c); //父类public成员可以访问
//System.out.println(b.d); //父类的default成员不可直接访问
}
}
三、final关键字
final
关键字可以用来修饰变量、成员方法和类。
1、修饰变量或字段,表示常量。
final int a = 10;
a = 20; // 常量不能被修改
2、修饰类,表示该类不能被继承。
final public class A {
}
public class B extends A {
public static void main(String[] args) {
}
}
3、修饰方法,表示方法不能被重写
public class A {
public final void method(){
System.out.println("A.method");
}
}
public class B extends A {
public void method(){ } //会报错
public static void main(String[] args) {
}
}
四、初始化(代码块执行顺序)
在没有继承关系时的执行顺序:
class Animal {
public String breed; //品种
public String name; //名字
public Animal(String breed, String name) {
this.breed = breed;
this.name = name;
System.out.println("构造方法");
}
{
System.out.println("实例代码块"); //有类的创建才会执行实例代码块
}
static {
System.out.println("静态代码块"); //只在类加载阶段执行一次,只执行一次
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal("雪纳瑞","小白");
}
}
当有继承关系时的执行顺序:
class Animal{
public String breed; //品种
public String name; //名字
public Animal(String breed, String name) {
this.breed = breed;
this.name = name;
System.out.println("父类构造方法");
}
{
System.out.println("父类实例代码块");
}
static {
System.out.println("父类静态代码块");
}
}
class Dog extends Animal{
public Dog(String breed,String name){
super(breed, name);
System.out.println("子类的构造方法");
}
{
System.out.println("子类的实例代码块");
}
static {
System.out.println("子类静态代码块");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal("美洲豹","旺财"); //实例化父类
System.out.println("<<<<<<<<<<<<<<<<我是分隔线>>>>>>>>>>>>>>>");
Dog dog = new Dog("拉布拉多","金毛"); //实例化子类
}
}
结论:
- 静态代码块都只执行一次
- 父类静态代码块最早执行,且优先于子类静态代码块执行
- 父类实例代码块和父类构造方法紧接着执行
- 子类的实例代码块和子类构造方法紧接着再执行