关键字和API

本文详细解析了Java中的this和super关键字在构造器、成员变量访问中的作用,native关键字的含义和用法,final关键字修饰类、方法和变量的含义,以及Object类的基础知识和JavaBean规范。讨论了如何处理成员变量和方法重写,以及equals和hashCode的实现要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.1 this和super关键字

1.this和super的意义

this:当前对象

  • 在构造器和非静态代码块中,表示正在new的对象

  • 在实例方法中,表示调用当前方法的对象

super:引用父类声明的成员

无论是this和super都是和对象有关的。

2.this和super的使用格式
  • this

    • this.成员变量:表示当前对象的某个成员变量,而不是局部变量

    • this.成员方法:表示当前对象的某个成员方法,完全可以省略this.

    • this()或this(实参列表):调用另一个构造器协助当前对象的实例化,只能在构造器首行,只会找本类的构造器,找不到就报错

  • super

    • super.成员变量:表示当前对象的某个成员变量,该成员变量在父类中声明的

    • super.成员方法:表示当前对象的某个成员方法,该成员方法在父类中声明的

    • super()或super(实参列表):调用父类的构造器协助当前对象的实例化,只能在构造器首行,只会找直接父类的对应构造器,找不到就报错

3.避免子类和父类声明重名的成员变量

特别说明:应该避免子类声明和父类重名的成员变量

因为,子类会继承父类所有的成员变量,所以:

  • 如果重名的成员变量表示相同的意义,就无需重复声明

  • 如果重名的成员变量表示不同的意义,会引起歧义

在阿里的开发规范等文档中都做出明确说明

4.解决成员变量重名问题
  • 如果实例变量与局部变量重名,可以在实例变量前面加this.进行区别

  • 如果子类实例变量和父类实例变量重名,并且父类的该实例变量在子类仍然可见,在子类中要访问父类声明的实例变量需要在父类实例变量前加super.,否则默认访问的是子类自己声明的实例变量

  • 如果父子类实例变量没有重名,只要权限修饰符允许,在子类中完全可以直接访问父类中声明的实例变量,也可以用this.实例访问,也可以用super.实例变量访问

  • 变量前面没有super.和this.

    • 在构造器、代码块、方法中如果出现使用某个变量,先查看是否是当前块声明的==局部变量==,

    • 如果不是局部变量,先从当前执行代码的==本类去找成员变量==

    • 如果从当前执行代码的本类中没有找到,会往上找==父类声明的成员变量==(权限修饰符允许在子类中访问的)

  • 变量前面有this.

    • 通过this找成员变量时,先从当前执行代码的==本类去找成员变量==

    • 如果从当前执行代码的本类中没有找到,会往上找==父类声明的成员变量(==权限修饰符允许在子类中访问的)

  • 变量前面super.

    • 通过super找成员变量,直接从当前执行代码的直接父类去找成员变量(权限修饰符允许在子类中访问的)

    • 如果直接父类没有,就去父类的父类中找(权限修饰符允许在子类中访问的)

5.解决成员方法重写后调用问题
  • 如果子类没有重写父类的方法,只有权限修饰符运行,在子类中完全可以直接调用父类的方法;

  • 如果子类重写了父类的方法,在子类中需要通过super.才能调用父类被重写的方法,否则默认调用的子类重写的方法

  • 方法前面没有super和this.

    • 先从子类找匹配方法,如果没有,再从直接父类找,再没有,继续往上追溯

  • 方法前面有this.

    • 先从子类找匹配方法,如果没有,再从直接父类找,再没有,继续往上追溯

  • 方法前面有super.

    • 从当前子类的直接父类找,如果没有,继续往上追溯

1.2 native关键字(了解)

1.native的意义

native:本地的,原生的

2.native的语法

native只能修饰方法,表示这个方法的方法体代码不是用Java语言实现的,而是由C/C++语言编写的。但是对于Java程序员来说,可以当做Java的方法一样去正常调用它,或者子类重写它。

JVM内存的管理:

区域名称作用
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。

1.3 final关键字

1.final的意义

final:最终的,不可更改的

2.final修饰类

表示这个类不能被继承,没有子类

final class Eunuch{//太监类
	
}
class Son extends Eunuch{//错误
	
}
3.final修饰方法

表示这个方法不能被子类重写

class Father{
	public final void method(){
		System.out.println("father");
	}
}
class Son extends Father{
	public void method(){//错误
		System.out.println("son");
	}
}
4.final修饰变量

final修饰某个变量(成员变量或局部变量),表示它的值就不能被修改,即常量,常量名建议使用大写字母。

如果某个成员变量用final修饰后,不能有set方法,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)

1.4 Object根父类

1.如何理解根父类

java.lang.Object是类层次结构的根类,即所有类的父类。每个类都使用 Object 作为超类。

  • Object类型的变量与除Object以外的任意引用数据类型的对象都多态引用

  • 所有对象(包括数组)都实现这个类的方法。

  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:

public class MyClass /*extends Object*/ {
  	// ...
}
2.Object类的其中5个方法

API(Application Programming Interface),应用程序编程接口。Java API是一本程序员的字典 ,是JDK中提供给我们使用的类的说明文档。所以我们可以通过查询API的方式,来学习Java提供的类,并得知如何使用它们。在API文档中是无法得知这些类具体是如何实现的,如果要查看具体实现代码,那么我们需要查看src源码

根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。今天我们主要学习其中的5个:

(1)toString()

方法签名:public String toString()

①默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

②通常是建议重写

③如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

因为Java的引用数据类型的变量中存储的实际上时对象的内存地址,但是Java对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM帮你调用了对象的toString()。

(2)getClass()

public final Class<?> getClass():获取对象的运行时类型

因为Java有多态现象,所以一个引用数据类型的变量的编译时类型与运行时类型可能不一致,因此如果需要查看这个变量实际指向的对象的类型,需要用getClass()方法

	public static void main(String[] args) {
		Object obj = new Person();
		System.out.println(obj.getClass());//运行时类型
	}

(3)equals()

public boolean equals(Object obj):用于判断当前对象this与指定对象obj是否“相等”

①默认情况下,equals方法的实现等价于与“==”,比较的是对象的地址值

②我们可以选择重写,重写有些要求:

A:

B:如果重写equals,那么一定要遵循如下几个原则:

a:自反性:x.equals(x)返回true

b:传递性:x.equals(y)为true, y.equals(z)为true,然后x.equals(z)也应该为true

c:一致性:只要参与equals比较的属性值没有修改,那么无论何时调用结果应该一致

d:对称性:x.equals(y)与y.equals(x)结果应该一样

e:非空对象与null的equals一定是false

(4)hashCode()

public int hashCode():返回每个对象的hash值。

如果重写equals,那么通常会一起重写hashCode()方法,hashCode()方法主要是为了当对象存储到哈希表(后面集合章节学习)等容器中时提高存储和查询性能用的,这是因为关于hashCode有两个常规协定:

  • ①如果两个对象的hash值是不同的,那么这两个对象一定不相等;

  • ②如果两个对象的hash值是相同的,那么这两个对象不一定相等。

重写equals和hashCode方法时,要保证满足如下要求:

  • ①如果两个对象调用equals返回true,那么要求这两个对象的hashCode值一定是相等的;

  • ②如果两个对象的hashCode值不同的,那么要求这个两个对象调用equals方法一定是false;

  • ③如果两个对象的hashCode值相同的,那么这个两个对象调用equals可能是true,也可能是false

(5)finalize()

protected void finalize():用于最终清理内存的方法

面试题:对finalize()的理解?

  • 当对象被GC确定为要被回收的垃圾,在回收之前由GC帮你调用这个方法,不是由程序员手动调用。

  • 这个方法与C语言的析构函数不同,C语言的析构函数被调用,那么对象一定被销毁,内存被回收,而finalize方法的调用不一定会销毁当前对象,因为可能在finalize()中出现了让当前对象“复活”的代码

  • 每一个对象的finalize方法只会被调用一次。

  • 子类可以选择重写,一般用于彻底释放一些资源对象,而且这些资源对象往往时通过C/C++等代码申请的资源内存

(6)重写toString、equals和hashCode方法(Alt+Insert)

建议使用IDEA中的Alt + Insert快捷键,而不是Ctrl + O快捷键。

3.标准JavaBean

JavaBean 是 Java语言编写类的一种标准规范。符合JavaBean 的类,要求:

(1)类必须是具体的和公共的,

(2)并且具有无参数的构造方法,

(3)成员变量私有化,并提供用来操作成员变量的setget 方法。

(4)重写toString方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值