Java中重要的关键字
static
static
可以可以出现的位置:
- 修饰成员变量:静态属性
- 修饰成员方法:静态方法
- 修饰代码块:静态代码块
- 修饰内部类:静态内部类
- 注意:
static
不可修饰局部变量!!! - 被static修饰的语句,都有一个共同的特点,都与这个类所构建的对象没有关系了,他是独一份的。例如:属性是每个对象所独有的,而静态的属性是被所有对象所共享的(这一点可以泛化的去理解
static
修饰的任何语句)。
修饰属性
- 当
static
修饰属性的时候,该属性就会变成静态属性,静态属性是所有对象所共享的。 - 要使用静态属性(非
private
修饰)的时候,可以使用对象.静态属性名
的方式,也可以使用类名.静态属性名
的方式,而属性却仅仅可以使用对象.属性名
的方式。
class A {
public static final String a = "123";
}
public class Main {
public static void main(String[] args) {
String x = A.a;//方法1
String y = new A().a;//方法2
}
}
修饰方法
- 当
static
修饰方法的时候,该方法变为静态方法。 - 使用静态方法的方式,和静态属性是一样的,即
对象.静态方法名
和类名.静态方法名
都是可以的。 - 注意: 由于静态方法不依赖任何对象,可以直接调用,所以也就没有
this
的概念。即:在静态方法中不能访问非静态成员方法和非静态成员属性,但是在非静态成员方法中是可以访问静态成员方法/成员属性的。即: - ①在静态上下文中(静态方法),只能使用静态属性和静态方法。
- ②在非静态上下文中(非静态方法),可以使用,静态属性、静态方法和非静态属性、非静态方法。
修饰代码块
- 当
static
修饰代码块的时候,可能有多种用途。这里举两个例子: - 可以用于静态属性的初始化。
- 可以用于类加载时,执行相应的代码。
- 注意: 静态代码块在一个类中,可以出现多个,且位置随意,当这个类进行类加载的时候,会按顺序依次执行静态代码块的内容,且只会执行一次(因为在程序运行期间,只会加载一次类)。
- 还需注意,虽然代码块可以出现在方法内部,但是,静态代码块不可出现在任何方法内部,因为静态代码块的执行时机是类加载的时候,是主动执行的,但是,如果放在方法内部,那么该方法就被被动执行了,显然是不行的。
public class Main {
public static int a;
static {
a = 10;
}
public static void main(String[] args) {
System.out.println("I'm second one!");
System.out.println("a = " + a);
}
static {
System.out.println("I'm first one!");
}
}
执行结果为:
修饰内部类
static
修饰内部类的时候,用法和static
修饰属性的时候,基本上差不多。- 就是当你需要使用这个类的时候,需要或不需要使用实例对象来进行调用。
class A {
class B {
public int b;
}
static class C {
public int c;
}
}
public class Main {
public static void main(String[] args) {
A.B b = new A().new B();//b是属于一个对象的
A.C c = new A.C();//c不属于任何对象
A a = new A();
A.B b1 = a.new B();//可行的
A.C c1 = a.new C();//不可行,我还没有弄懂,如果有人知道,请在评论区解答,谢谢了
}
}
final
final
关键字可以出现的三个位置:
- 修饰变量
- 修饰方法
- 修饰类
修饰变量
final
修饰变量,可被修饰的变量可以是属性/静态属性/局部变量/形式参数(可以和局部变量进行合并)
,当一个变量被final
修饰的时候,该变量只有一次被赋值的机会。
public class Test2 {
final int a = 10;
{
a = 20;//此时出现错误,不允许二次赋值×
}
}
修饰方法
final
修饰方法,代表该方法不可被其子类重写。- 注意: 这里的方法指的是普通方法,因为,在静态方法中
static
和final
没有必要同时出现,被static
修饰的方法,是不会继承给子类的,而被final
修饰的方法,是不可被重写的,因此一个在子类中看都看不到的方法,又规定该方法不可被重写,完全是多此一举。
public class Main extends A {
@Override
public void fun1() {//无法重写×
}
@Override
public void fun2() {//可以重写√
}
}
修饰类
final
修饰类,如果一个类被final
所修饰,那么这个类不可被继承,也就是说,这个类不可能拥有任何子类。
final class A{
public int a;
}
public class Main extends A {//错误操作×
}
abstract
abstract
可以出现的位置:
- 修饰方法
- 修饰类
修饰类
- 一个类被
abstract
修饰,那么该类就叫做抽象类
,抽象类是无法实例化出实例对象的。
修饰方法
- 一个方法被
abstract
修饰,那么该方法就叫做抽象方法
,定义于父类中的抽象方法,是专门留给子类去实现的,且子类必须实现,该方法只有方法签名,没有方法体,且不能有方法体。 - 注意: 抽象方法只能出现在抽象类中,但抽象类中不一定只有抽象方法。
abstract class A {
public abstract void method(int a, int b);
public void method2() {
System.out.println("This is from class A");
}
}
public class Main extends A {
@Override
public void method(int a, int b) {//必须实现该方法
System.out.println(a - b);
}
public void myMethod() {
method2();
}
}
this
this
关键字的作用:
this
是一个引用,它的引用类型为:this
出现在哪个类下,this
的类型就是该类的引用(如果不存在子父类的继承关系,可以简单理解为这样,复杂情况后面详述)。this
一定不为null
,一定指向当前对象。- 当子类父类中,出现同名方法或属性的时候,
this
可以明确调用自己的方法(可以省略)。 this
可以作为方法名(构造方法),用于调用本类的构造方法,但是只能出现在构造方法的第一句。
public class Main{
int a;
int b;
public Main(int a,int b) {
this.a = a;
this.b = b;
}
public Main(){
this(10,20);//必须放在第一句
}
public void method(){
this(10,20);//报错:对this的调用必须是构造器中的第一个语句
}
}
class Parent {
public void method() {
System.out.println("This is Parent!");
}
}
public class Main extends Parent {
@Override
public void method() {
System.out.println("This is Son!");
}
public void out() {
super.method();
this.method();
}
public static void main(String[] args) {
Main a = new Main();
a.out();
}
}
输出结果为:
super
super
关键字的作用:
- 明确调用父类的构造方法,只能出现在子类的构造方法中,且必须为第一句,和
this
的使用类似。 - 此时会不会有一个疑问呢,
this
只能放在第一行,super
也只能放在第一行,两个同时出现怎么办?其实不会出现这样的情况的,因为当你使用this
去调用其它构造方法的时候,被调用的构造方法中,已经显/隐式的调用了super
方法了,此时,你没有必要再调一遍super
。 - 如果子类构造方法中,没有写
super
那么默认隐含的调用父类无参构造方法。 super
可作为(“看作”)指向"父类对象"(实际不存在)的引用。
当子类中,出现同名属性和方法时,应该怎么识别呢?
this.xxx
优先在子类中查找属性和方法,没有找到时,才会去父类中匹配父类的属性和方法。super.xxx
直接去父类中匹配父类的属性和方法。(注意: 如果在父类中找不到,不会再回到子类中继续查找)
class Parent {
public void method() {
System.out.println("This is Parent!");
}
}
public class Main extends Parent {
public void out() {
this.method();
}
public static void main(String[] args) {
Main a = new Main();
a.out();
}
}
将会输出:This is Parent!
在继承关系下的super和this
先来看一段代码:
class A {
public String a = "A";
public void fun2() {
this.fun3();//或fun3();执行结果一样
System.out.println(this.a);
}
public void fun3() {
System.out.println("This is fun3 in A");
}
}
public class Main extends A {
public String a = "Main";
public void fun1() {
super.fun2();
}
@Override
public void fun3() {
System.out.println("This is fun3 in Main");
}
public static void main(String[] args) {
Main x = new Main();
x.fun1();
}
}
输出结果为:
- 执行结果为:
- 方法:子类中的
fun3()
,即:This is fun3 in Main
。 - 属性:父类中的
a
,即:A
; - 我们首先看看多态的定义:多态: 相同类型的引用执行同一个方法时,呈现出不同的行为特征,这就是多态。也就是说,属性并没有多态性。继承的时候,方法会被转移至子类中,但是属性并不会。说白了,引用只是一个引用,真正要执行哪个方法,还是要看这是个什么对象。即:访问变量看声明,访问方法看实际对象类型
- 尽管这里明确强调,引用为父类引用,但是其实际指向的对象为子类对象,因此,执行方法时,体现多态特性,即调用子类的方法(如果子类重写了该方法)。
如果任何理解错误,或者是更好的理解,请指出来,谢谢了😁~