方法说明
指一些已经预先定义好的,暴露给外界使用的方法或者工具
隐式继承
public final native Class<?> getClass();
说明:
首先它的访问权限修饰符是public
,可以任意访问,没有访问权限问题。
final
修饰它,表示它无法被重写。
native
表示该方法是一个本地方法,指的是Java调用其它语言(主要是C/C++)的实现来完成功能的方法。本地方法不需要方法体,我们也不会考虑它的实现细节。(该方法的作用可以通过查阅API文档了解)
Class>是返回值类型,表示该方法需要返回一个Class对象。
上述>表示泛型,关于泛型后面会详细讲。
作用:通过一个本地方法的实现,去获取Class对象。
具体来说,某个类的运行时类对象,就是该类的Class对象
。
某个类的Class对象当中,包含了该类的所有类型信息(比如类名是啥,有哪些方法、变量、构造器等)
于是程序员在程序的运行时期,只需要获取该类的Class对象,就能够获取类型信息了。
getClass()
方法只是获取Class对象,该方法不负责创建Class对象。源码:
public String toString{}{
getClass().getName() + '@' + Integer.toHexString(hashCode());
}
说明:
getClass().getName()
:全类名
Integer.toHexString(hashCode())
:十六进制地址值
作用:
返回该对象的字符串表示。
重写toString的方法:
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
注意事项:
toString()
方法可以快速自动生成,仍然使用IDEA快捷键Alt + Insert
完成。
toString()
方法,普遍来说就是为了完成打印成员变量取值的,不要在里面写一些奇怪的代码。
如果类中有(自定义)引用数据类型成员变量,也需要重写它的toString
方法,不然就会打印地址值了。
源码:
public boolean equals(Object obj) {
return (this == obj);
}
说明:
参数需要传入一个对象
默认实现:判断当前这个对象是否跟参数对象一样
只有当两个引用完全指向同一个对象时,方法才会返回true,否则都会返回false。
equals 方法在非空对象引用上实现相等关系:
@Override
public boolean equals(Object o) {
// 自反性
if (this == o) return true;
// 排他性
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
// 比较成员变量的值
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
在实现排他性时,实际上有两种选择:
使用getClass
方法比较。 这个比较是比较苛刻的,只有在完全是同一个类型时才会返回true
使用instanceof
比较。
引用 instanceof 类名
表示判断引用所指向的对象的具体类型,是否是后面类名的对象或者子类对象,如果是就返回true,如果不 是就返回false。
这个比较的条件就比较宽松了,可以允许传入子类对象。(当子类对象的父类成员和父类对象相同时,equals方法仍然返回true)
@Override
public boolean equals(Object o) {
// 自反性
if (this == o) return true;
// 排他性
//if (o == null || getClass() != o.getClass()) return false;
if(o == null) return false;
// 类型扩大,可以判断子类
if(!(o instanceof Student)) return false;
Student student = (Student) o;
// 比较成员变量的值
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
equals方法也是可以用快捷键自动生成的,使用快捷键alt + insert
。而且可以选择在实现排它性时的方式。
浮点数比较特殊,它具有规格化和非规格化的区别,还有非数(NaN),无穷大,无穷小很多特殊的概念,正常情况下,如果仅仅比较数值,用==比较相等是够用的。但为了避免因浮点数特殊值,而出现的错误。实际开发中,从严谨角度出发,浮点数的比较仍然建议使用,对应包装类型的compare
方法去比较浮点数的大小:
Float.compare(float a,float b)
Double.compare(double a,doublet b)
这两个方法在,a < b时返回-1(负数),在a>b时,返回1(正数),只有在两个浮点数相等时,才会返回0
如果类中有引用数据类型成员变量,需要去调用它们的equals方法完成比较。这就意味着还需要重写这个类的equals方法。
财务金额上的运算是不推荐使用浮点数的,会出现精度问题。推荐使用BigDecimal
这个类完成运算。
eg:
// 不会出现精度问题
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("0.9");
BigDecimal sub = b1.subtract(b2);
System.out.println(sub);
BigDecimal addNumber = b1.add(b2);
System.out.println(addNumber);
}
映射不要求元素一一对应,允许出现多对一,但绝不允许一对多。
public native int hashCode();
很显然,它是一个本地方法,这个方法也没有任何参数,返回值是一个int类型整数。
java.util.Hashtable
提供的哈希表)的性能。实际上,由 Object
类定义的 hashCode
方法确实会针对不同的对象返回不同的整数。
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals比较时所用的信息没有被修改。
如果根据 equals(Object)
方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。
如果根据 equals(java.lang.Object)
方法,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
hashCode
方法和equals
方法是息息相关的,要重写必须一起重写
。
使用快捷键Alt + Insert
首先hashCode
方法中规定:
那么这里就很明显存在一个问题:
如何判断对象相等? ----> 答:依赖类中的equals
方法!
protected void finalize() throws Throwable { }
说明:
首先注意访问权限是protected,这说明在不重写访问权限的情况下,仅能够在自身类中创建自身对象,才能调用这个方法。
其次它的方法体是空的,功能没有实现,这种设计的目的是为了让子类自己去重写该方法的实现。这种做法比起抽象方法的强制子类实现,要更加灵活,而且可以用在普通类中。
最后,它的方法声明中有一个throws Throwable
, 这是方法抛出异常列表的声明。
Java当中的finalize
方法就是"模仿"析构函数设计的,finalize方法也会在对象销毁时自动被调用,
public class Demo {
public static void main(String[] args) {
// 匿名对象,理论上很快成为垃圾对象
new Student();
// 通知GC进行垃圾回收
System.gc();
}
}
class Student{
@Override
protected void finalize() throws Throwable {
System.out.println("模拟释放资源");
}
}
在Java中,所有的资源释放,都必须依赖程序员手动完成,所以以后大家做I/O操作,网络操作,数据库操作等需要占用系统资源的操作时,一定不要忘记在用完后,释放系统资源!
clone方法的方法声明为:
protected native Object clone() throws CloneNotSupportedException;
这里需要注意的地方有:
首先注意访问权限,它的访问权限是protected
。这意味着:
它是一个本地native
方法,没有方法体。(依赖本地方法实现创建对象,不同于new对象)
返回值类型是Object
。
这里,也建议在子类方法中重写这个返回值类型。
throws CloneNotSupportedException
是方法抛出异常的声明,
Object
类当中的clone
方法默认实现,就是得到一个独立的,和原先对象成员一致的新对象。
clone
方法,修改权限clone
方法的类,实现cloneable
接口cloneable
是一个空接口,起到标记的作用概念:
如果类中有引用数据类型的成员变量,那么clone方法的使用就要格外注意了:
像以上Object类当中的clone方法的实现,直接拷贝一份成员变量,不管引用数据类型成员变量引用,所指向的对象。我们称之为"浅克隆"。
代码演示:
@Override
protected User clone() throws CloneNotSupportedException{
return (User)super.clone();
}
概念:
如果能够让引用数据类型成员变量之间也能相互独立,克隆后获取真正独立的两个对象。我们称之为"深度克隆"。
代码演示:
@Override
protected User clone() throws CloneNotSupportedException{
// 1. 深克隆在浅拷贝的基础上进行修改
User cloneUser = (User)super.clone();
// 2. 把Address这个引用再clone一份
Address cloneAddress = this.address.clone();
// 3.赋值给克隆出的User对象的address,就是将拷贝引用指向拷贝对象
cloneUser.address = cloneAddress;
return cloneUser;
}