【Java】常见关键字

1.this关键字的用法

💗在成员方法内部,this表示对“调用方法的那个对象”的引用
💫方法形参或局部变量与成员变量同名时,成员变量被隐藏,通过“this.成员变量名”使用成员变量
💫this可作为返回值,返回对当前对象的引用
💗在构造方法内部,通过this调用当前类的另一个构造方法(见“构造方法重载”)

在这里插入图片描述

在这里插入图片描述
💗在成员方法内部

public class Leaf {
	int i;
	Leaf(int i){
		this.i = i;  //任何一个对象除了基本的成员变量以外,还有一个区域是this,this是个对象,指向自身
	}
	Leaf increment() {//成员方法,返回值为Leaf类型
		i++;
		return this;
	}
	void print() {
		System.out.println("i = "+i);
	}
	public static void main(String[]args) {
		Leaf leaf = new Leaf(100);
		leaf.increment().increment().print();//102
		//为了便于理解,上面这一句等效于下面三句
		Leaf leaf2 = leaf.increment();
		Leaf leaf3 = leaf2.increment();
		leaf3.print();
		}

}

进入leaf(int i){}
在这里插入图片描述
跳出leaf(int i){},结束Leaf leaf = new Leaf(100);局部变量被销毁。
在这里插入图片描述
leaf.increment().increment();
在这里插入图片描述
💗在构造方法内部

public class Leaf {
	int i;
	Leaf(int i){
		this.i = i; 
	}
	Leaf(){
		this(1);//在构造方法内部,通过this调用当前类的另一个构造方法
		//等价于在main函数中Leaf(1),但构造方法只能和new一起
	}
	public static void main(String[]args) {
		Leaf leaf = new Leaf();
	}
}
2.super关键字的用法

super和this类似,都是在堆中的对象里占用空间。

💗表示“当前对象的父类对象的引用”,用来引用父类中的成员变量或方法。
💗在子类构造方法中,通过“super([参数列表]);”调用父类的构造方法。该语句必须出现在子类构造方法的第一行。

💗对当前对象的父类对象的引用

public class TestInheritance{
	public static void main(String[] args){
		Rectangle rect=new Rectangle();
		rect.newDraw();
	}
}
class Shape{
	public void draw(){ System.out.println("Draw shape"); }
}
class Rectangle extends Shape{
	public void draw(){ System.out.println("Draw Rectangle"); }
	public void newDraw(){
		draw();
		super.draw();
	}
}

输出结果为:

Draw Rectangle
Draw shape

在这里插入图片描述

package java001;

class FatherClass{
	public int value;
	public void f() {
		value=100;
		System.out.println("FatherClass,value:"+value);
	}
}
class ChildClass extends FatherClass{
	public int value;
	public void f() {
		super.f();
		value = 200;
		System.out.println("ChildClass.value:"+value);
		System.out.println(value);
		System.out.println(super.value);
	}
}
public class TestInherit {
	public static void main(String[]args) {
		ChildClass cc = new ChildClass();
		cc.f();
	}
}

在这里插入图片描述
在这里插入图片描述

💗调用父类的构造方法

package java001;

class SuperClass{
	private int n;
	SuperClass(){
		System.out.println("SuperClass()");
	}
	SuperClass(int n){
		System.out.println("SuperClass("+n+")");
		this.n=n;
	}
	void getSuperN() {
		System.out.println("Super N:"+n);
	}
}
class SubClass extends SuperClass{
	private int n;
	SubClass(int n){
		System.out.println("SubClass("+")");
		this.n=n;
	}
	SubClass(){
	    //super();默认的
		super(300);//调用父类的构造方法,一定要放在子类构造方法的第一行,如果不写这一行代码,电脑会自动默认调用父类的无参数的构造方法。
		System.out.println("SubClass()");
	}
	void getSubN() {
		System.out.println("Sub N:"+n);
	}
}

public class TestSuperSub {
	public static void main(String[]args) {
		SubClass sc = new SubClass();
		//可以这样理解:
		//这句代码把SuperClass中的变量和方法空间创建出来,又创建了SubClass的变量和方法空间,调用SubClass()构造方法(进入SunClass()行数第一步就去调用SuperClass()构造方法)和SuperClass()构造方法。(如果没有super(300);会自动调用super();)
		//父类优先
		sc.getSuperN();
		sc.getSubN();
	}

}

在这里插入图片描述

在这里插入图片描述

💦子类对象的创建与初始化的一般步骤💦SubClass sc = new SubClass();
1.子类构造方法调用父类构造方法:
通过显式的super()方法调用或编译器隐含插入的super()方法调用(子类构造方法的第一句),这一过程递归地进行(多重继承关系时),直到根类Object的构造方法。在这一过程中,子类对象所需的所有内存空间被分配,所有成员变量均使用默认值初始化
2.从根类Object的构造方法开始,自顶向下地对每个类依次执行如下两步:
显式初始化
执行构造方法的主体(不包括使用super调用父类构造方法)。

3.static关键字(可修饰类成员变量和成员方法)
3.1静态变量

静态变量:在类的成员变量声明中带有static关键字的变量。

在这里插入图片描述
静态变量的创建:

  • 静态变量的创建与实例对象无关。
  • 只在系统加载其所在分配空间并初始化,且在创建该类的实例对象不再分配空间。
    在这里插入图片描述
    代码建议仔细阅读,后面有注释,含有变量、构造方法调用的顺序。
package java004;
//在调用构造方法之前,先把对应类中的变量创建出来,若有static变量,按从上往下的顺序创建(调用构造方法),再创建普通变量
//若static变量之前创建过,再次遇到时跳过,而普通变量需要再次被创建、调用构造方法,如main函数中的两个new Cupboard();
class Bowl {
    Bowl(int i) { System.out.println("Bowl(" + i + ")"); }
    void f1(int i) { System.out.println("f1(" + i + ")"); }
}
class Table {
    static Bowl bowl1 = new Bowl(1);
    Table() {
        System.out.println("Table()");
        bowl2.f1(1);
    }
    void f2(int i) { System.out.println("f2(" + i + ")"); }
    static Bowl bowl2 = new Bowl(2);
}
class Cupboard {
    Bowl bowl3 = new Bowl(3);
    static Bowl bowl4 = new Bowl(4);
    Cupboard() {
        System.out.println("Cupboard()");
        bowl4.f1(2);
    }
    void f3(int i) { System.out.println("f3(" + i + ")"); }
    static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {//这个类包含Static变量,加载这个类的时候,首先要加载Static变量
    public static void main(String[] args) {
        System.out.println("new Cupboard() in main");
        new Cupboard();//在调用构造方法之前,bowl3会再被创建一次,调用new Bowl(3),输出Bowl(3),而静态变量只创建一次,故不再调用
        //调用构造方法,输出Cupboard()、f1(2)
        System.out.println("new Cupboard() in main");
        new Cupboard();//重复上面的new Cupboard();
        table.f2(1);
        cupboard.f3(1);
    }
    static Table table = new Table();//StaticInitialization类包含static变量,第一步,先执行这一句,在数据区创建table变量,接着在调用构造方法之前,先加载Table类的static变量,
    //在数据区创建bowl1变量,Bowl类中无静态变量,调用构造方法,输出Bowl(1)。接着,在数据区创建bowl2变量,Bowl类中无静态变量,调用构造方法,输出Bowl(2)。
    //静态变量加载完后,调用new Table()构造方法,输出Table()、f1(1);
    static Cupboard cupboard = new Cupboard();//第二步,数据区创建cupboard变量,接着在调用构造方法之前,先加载Table类的static变量,
    //在数据区创建bowl4变量,Bowl类中无静态变量,调用new Bowl(4)构造方法,输出Bowl(4)。接着,在数据区创建bowl5变量,Bowl类中无静态变量,调用构造方法,输出Bowl(5)。
    //在栈中创建变量bowl3,Bowl类中无静态变量,调用new Bowl(3)构造方法,输出Bowl(3)。
    //静态变量加载完后,调用new Cupboard()构造方法,输出Cupboard()、f1(2)
    //进入main函数
}

非private的静态变量,可在类外用类名访问(一下两种均可)

class Employee{
private int id;
public static int serialNum = 1;
Employee(){ id=serialNum ++; }
}
class OtherClass{
public static void main(String[] args){
      System.out.println(Employee.serialNum);
}
}
class Employee{
private int id;
public static int serialNum = 1;
Employee(){ id=serialNum ++; }
}
class OtherClass{
public static void main(String[] args){
      Employee e=new Employee();
      System.out.println(e.serialNum);
}
}
3.2静态方法
  • 静态方法:在类的成员方法声明中带有static关键字的方法。
  • main方法是静态方法、程序入口点,不创建实例对象就可以运行该方法
  • 静态方法一般通过类名访问,但特殊情况下也可通过实例对象访问。
class GeneralFunction {
	public static int add(int x, int y) {
		return x + y;
	}
}
public class UseGeneral {
	public static void main(String[] args) {
		int c = GeneralFunction.add(9, 10);
		System.out.println("9 + 10 = " + c);
	}
}

静态方法中没有this引用,需要将实例传入参数才可访问。因此,静态方法不能直接调用实例方法,也不能直接访问所属类的实例成员变量,但可以访问静态变量和静态方法。

public class TestStaticMethod{
	public static void main(String[] args){
		StaticMethod obj=new StaticMethod();
		StaticMethod.sPrintXAndY(obj);		}
}
class StaticMethod{
	int x=0;		static int y=1;
	public void iPrintAndIncreaseY(){
		sPrintY(); 
		y++;
	}
	public static void sPrintY(){
		//System.out.println(this.x);	//不能访问实例成员变量
		//iPrintAndIncreaseY();		//不能访问实例方法
		System.out.println(StaticMethod.y);	//可以访问静态变量
	}
	public static void sPrintXAndY(StaticMethod o){
		System.out.println(o.x);	//可以通过o引用访问实例成员变量
		o.iPrintAndIncreaseY();	//可以通过o引用调用实例方法
		sPrintY();		//可以直接调用静态方法
	}

静态方法的重写:
回顾方法重写的规则:
不改变方法的名称、参数列表和返回值,改变方法的内部实现
子类中重写方法的访问权限不能缩小
子类中重写方法不能抛出新的异常
父类中private的成员,在子类中不能被覆盖(重写)
本节加入以下重写规则:
子类不能把父类的静态方法重写为非静态
子类不能把父类的非静态方法重写为静态
子类可以声明与父类静态方法相同的方法
//静态方法的重写不会导致多态性
//构造方法可以看成是static方法,不具有多态性

在这里插入图片描述

4.final关键字

final的使用位置
1.在类声明中使用:表示类不能被继承。
2.在成员方法声明及方法参数中使用:成员方法不能被重写,参数变量值不能更改。
3.在成员变量和局部变量声明中使用:表示变量的值不能更改。

4.1在类声明中使用final关键字

被定义成final的类不能再派生子类
例: final class Employee {…}
class Manager extends Employee { …}

4.2在成员方法声明中使用final关键字

被定义成final的方法不能被重写。
//将方法定义为final可使运行时的效率优化
//对于final方法,编译器直接产生调用方法的代码,而阻止运行时刻对方法调用的动态绑定
private的方法都隐含指定为是final的,对子类不可见就无所谓被重写。

4.3在方法参数中使用final关键字

将方法参数指明为final,则无法在方法中更改参数的值

//Cat类含有name和eyeColor两个成员变量
public void m2(final int j) { // final变量不能改变值,final方法不能被重写
		//j = 10; 报错
	}
	
	public void mCat(final Cat c) {  
		c.eyeColor = "black";//重要!!!!不报错,引用不能改变,但堆里的内容可以改变
		//c = new Cat("name", "color"); 报错,指向新的引用
	}
}
4.4在成员变量中使用final关键字

在这里插入图片描述

class T {
	final int i = 8; //final的变量不能改变值, c++ -> const
	public final void m() { //final方法不能被重写
		//i = 8; 让i=8仍会报错,因为编译器会理解为你在试图改变i的值
	}
}

空白final:若final成员变量声明时未赋初值,则在所属类的每个构造方法中都必须对该变量赋值。

class Poppet {
	private int i;
	Poppet(int ii) { i = ii; }
}
public class BlankFinal {
	private final int i = 0; 	// 被初始化的final
	private final int j; 	// 空白final
	private final Poppet p; 	// 空白final引用
	public BlankFinal() {
		j = 1; 			// 初始化空白final
		p = new Poppet(1); 	// 初始化空白final引用
	}
	public BlankFinal(int x) {
		j = x; 			// 初始化空白final
		p = new Poppet(x); 	// 初始化空白final引用
	}
	public static void main(String[] args) {
		new BlankFinal();
		new BlankFinal(47);
	}
}
4.5在局部变量中使用final关键字

被定义成final的局部变量可以在所属方法的任何位置被赋值,但只能赋一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值