博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java——常用类
阅读量:3956 次
发布时间:2019-05-24

本文共 11988 字,大约阅读时间需要 39 分钟。

文章目录

一、sun公司下的JDK

在这里插入图片描述

在这里插入图片描述

二、JDK类库的根类:Object

1. Object类的概述

在这里插入图片描述

这个老祖宗类中的方法我们需要先研究一下,因为这些方法都是所有子类通用的。任何一个类默认继承Object。就算没有直接继承,最终也会间接继承。

2. Object类中的常用方法

2.1 我们怎么找这些方法?

  • 方式一:去源代码当中看(但是这种方法比较麻烦,源代码也比较难)
  • 方式二:去查阅java类库的帮助文档

2.2 什么是API?

应用程序编程接口(Application Programming Interface)

整个JDK的类库就是一个javase的API

SUN公司提前写好的这套类库就是API(一般每一份API都对应一份帮助文档)
在这里插入图片描述
在这里插入图片描述

注意:每一个API都会配置一套API帮助文档

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

3. 学习Object类中的toString()和equals()方法

方法 作用
protected Object clone() 负责对象克隆的
int hashCode() 获取对象哈希值的一个方法
boolean equals(Object obj) 判断两个对象是否相等
String toString() 将对象转换成字符串形式
protected void finalize() 垃圾回收器负责调用的方法

3.1 关于Object类中的toSting()方法

源代码长什么样?

public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode()); }

源代码上toString()方法的默认实现是:

类名@对象的内存地址转换为十六进制的形式

Sun公司设计toString()方法的目的是什么?

  • toString()方法的作用是?:设计目的是通过调用这个方法可以将一个“java对象”转换成“字符串表示形式”
  • 其实Sun公司开发JAVA语言的时候,建议所有的子类都去重写toString()方法。toString()方法应该是一个简洁的、详实的、易阅读的
  • System.out.println(引用);这里会自动调用"引用"的toString()方法
public class Test01 {
/* 源代码长什么样? public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } 源代码上toString()方法的默认实现是: 类名@对象的内存地址转换为十六进制的形式 */ public static void main(String[] args) {
MyTime t1 = new MyTime(1970,1,1); //一个日期对象转换成字符串形式的话,我可能还是希望能看到具体的日期信息 String s1 = t1.toString(); //MyTime类重写toString()方法之前 System.out.println(s1); //com.Object类.MyTime@4f023edb //MyTime类重写toString()方法之后 System.out.println(s1.toString()); //1970年1月1日 //同理,输出引用的时候会自动调用该引用的toString()方法 System.out.println(s1); //1970年1月1日 }}class MyTime{
int year; int month; int day; public MyTime(){
} public MyTime(int year, int month, int day) {
this.year = year; this.month = month; this.day = day; } //重写toString()方法,越简洁越好,可读性越强越好 public String toString(){
return this.year + "年" + this.month + "月" + this.day + "日"; }}

3.2 关于Object类中的equals()方法

equals方法的源代码

public boolean equals(Object obj) {
return (this == obj); }
  • 以上这个方法是Object类的默认实现
  • 在Object类中的equals方法当中,默认采用的是==判断两个java对象是否相等
  • 而==判断的是两个java对象的内存地址,我们应该判读两个java对象的内容是否相等,所以老祖宗的equals方法不够用,需要子类重写equals
  • 以后所有的类的equals方法都需要重写,因为Object中的equals方法比较的是两个对象的内存地址,我们应该比较内容,所以需要重写

Sun公司设计equals方法的目的是?

  • 以后编程的过程当中,都要通过equals方法来判断两个对象是否相等equals方法是判断两个对象是否相等
  • 判断两个java对象是否相等,不能使用==,因为==比较的是两个对象的内存地址
public class Test02 {
/* 1. equals方法的源代码 public boolean equals(Object obj) { return (this == obj); } 以上这个方法是Object类的默认实现 2. Sun公司设计equals方法的目的是? 以后编程的过程当中,都要通过equals方法来判断两个对象是否相等 equals方法是判断两个对象是否相等*/ public static void main(String[] args) {
//判断两个基本数据类型的数据是否相等,直接使用==就行 int a = 100; int b = 100; System.out.println(a==b); //true //创建一个日期对象是:2020年8月8日 MyTime2 t1 = new MyTime2(2020,8,8); //创建一个新的日期对象,日期也是:2020年8月8日 MyTime2 t2 = new MyTime2(2020,8,8); //判断两个java对象是否相等,我们使用==的话 //表示比较的是:t1中保存的对象内存地址和t2中保存的对象内存地址是否相等 System.out.println(t1 == t2); //false //重写Object对象之前(比较的是对象内存地址) //System.out.println(t1.equals(t2)); //false //重写Object对象之后(比较的是内容) System.out.println(t1.equals(t2)); //true //我们程序有bug,可以运行,但是效率特别低 MyTime2 t3 = null; System.out.println(t1.equals(t3)); //false }}class MyTime2 {
//extends Object int year; int month; int day; public MyTime2(){
} public MyTime2(int year, int month, int day) {
this.year = year; this.month = month; this.day = day; } /* Object类中默认存在 public boolean equals(Object obj) { return (this == obj); } */ //重写Object类中的equals方法 //至于怎么重写,自己定,认为两个对象什么相等的时候表示相等 /* public boolean equals(Object obj) { if(obj instanceof MyTime2){ MyTime2 t = (MyTime2)obj; if(this.year == t.year && this.month == t.month && this.day == t.day){ return true; } } return false; } */ //改良equals方法 public boolean equals(Object obj) {
//如果obj是空,直接返回false if (obj == null){
return false; } //如果obj不是一个Mytime2,没有必要比较了,直接返回false if(!(obj instanceof MyTime2)){
return false; } //如果this和obj保存的内存地址相同,没必要比较了,直接返回true if (this == obj){
return true; } //程序能走到这,说明obj一定是MyTime2类型 MyTime2 t = (MyTime2)obj; return this.year == t.year && this.month == t.month && this.day == t.day; }}

3.3 java语言中字符串String类也是重写toString()方法和equals()方法

  • String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equals。equals是通用的
  • String类也重写了toString方法了

总结:

  • java中基本数据类型比较是否相等,使用==
  • java中使用 " ==" 比较的是变量里面存储的值是否相等,如果String s = “abc”;String类型的变量s之间赋值进行比较,用 " == " 也是可以的。但是通过new对象的引用数据类型变量存储的是地址,不同变量存储的地址是不相同的,所以无法使用" =="进行比较
  • java中所有的引用数据类型统一使用equals方法来判断是否相等
public class Test03 {
public static void main(String[] args) {
//大部分情况下,采用这样的方式创建字符串对象 String s1 = "hello"; String s2 = "hello"; //实际上String也是一个类,不属于基本数据类型 //既然String是一个类,那么一定存在构造方法 String s3 = new String("Test1"); String s4 = new String("Test1"); //new两次,两个对象内存地址,==判断的是内存地址,不是内容 System.out.println(s3 == s4); //false System.out.println(s1 == s2); //true //比较两个字符串必须使用equals,String类已经重写了equals方法了 System.out.println(s3.equals(s4)); //true System.out.println(s1.equals(s2)); //true //String类也重写了toString方法了 String x = new String("pudding"); System.out.println(x.toString()); //pudding System.out.println(x); //pudding }}

public class Test04 {
public static void main(String[] args) {
//这样写的话以下的两种方式都是true和false,因为这里的字符串 /* Student s1 = new Student(111,"xingzhi"); Student s2 = new Student(111,"xingzhi"); System.out.println(s1.equals(s2)); //true System.out.println(s1 == s2); //false */ Student s1 = new Student(111,new String("xingzhi")); Student s2 = new Student(111,new String("xingzhi")); System.out.println(s1.equals(s2)); //true System.out.println(s1 == s2); //false }}class Student{
//学号 int no; //基本数据类型,比较时使用== //所在学校 String school; //引用数据类型,比较时使用:equals方法 public Student() {
} public Student(int no, String school) {
this.no = no; this.school = school; } //重写toString方法 public String toSting(){
return "学号" + no + ",所在学校名称" + school; } //重写equals方法 //需求:当一个学生的学号相等,并且学校相同时,表示同一个学生 //equals方法的编写模式都是固定的,架子差不多 public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Student)) return false; if (this == obj) return true; Student s = (Student)obj; //方法一: /* //这样写的话,上面通过equals比较就会出现错误 if (s.no == this.no && s.school == this.school){ return true; } */ //方法二: if (s.no == this.no && s.school.equals(this.school)){
return true; } return false; }}

3.4 equals方法重写要彻底

由于只是重写了User类里面的equals()方法,没有将Address类里面的equals()方法重写,会让我们的规则:当一个用户的用户名和家庭住址相同,不能表示同一个用户。因为Address中的equals方法仍然是继承Object类中的equals方法。

所以我们必须也将Address类中的equals方法也重写,重写equals方法彻底。结果如下

public class Test05 {
public static void main(String[] args) {
Address a1 = new Address("HF","YHQ","1111"); Address a2 = new Address("HF","YHQ","1111"); User u1 = new User("pudding",a1); User u2 = new User("pudding",a2); System.out.println(u1.equals(u2)); //true }}class User{
String name; Address addr; public User() {
} public User(String name, Address addr) {
this.name = name; this.addr = addr; } //重写equals()方法 //重写规则:当一个用户的用户名和家庭住址相同,表示同一个用户 //这个equals判断的是User对象和User对象是否相等//Object obj = u2[new User("pudding",a2)]; 这是一个多态(父类型引用指向子类型是自动类型转换) public boolean equals(Object obj){
if (obj == null || !(obj instanceof User)) return false; if (this == obj) return true; User u = (User)obj; //this.name.equals表示调用String类型的equals()方法,String类型默认重写了equals方法 //this.addr.equals表示调用Address类型的equals()方法,Address类型没有重写equals方法, //执行默认Object类型的equals方法,比较的仍然是对象的内存地址 //因为主方法中new了两个对象a1和a2所以这个this.addr.equals(u.addr)一定是false //姓名相同,地址相同表示同一个用户 if (this.name.equals(u.name) && this.addr.equals(u.addr)){
return true; } return false; }}class Address{
String city; String street; String zipcode; public Address() {
} public Address(String city, String street, String zipcode) {
this.city = city; this.street = street; this.zipcode = zipcode; } //注意:这里并没有重写equals方法 //这里的equals方法判断的是:Address对象和Address对象是否相等 public boolean equals(Object obj){
if (obj == null || !(obj instanceof Address)) return false; if (this == obj) return true; Address a = (Address)obj; //城市相同,街道相同,邮编相同,表示家庭地址相同 if (this.city.equals(a.city) && this.street.equals(a.street) && this.zipcode.equals(a.zipcode)){
return true; } return false; }}

4. 学习Object类中的finalize()方法

概述:

  • 这个方法是protected修饰的,在Object类中这个方法源代码是

    protected void finalize() throws Throwable { }
  • finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的

  • 这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。不像equals、toString方法,它们是需要你写代码再调用,而finalize方法只需要重写,重写完成将来GC会自动调用

  • finalize()方法执行时机:当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法

  • finalize()方法实际上是Sun公司为java程序员准备的一个时机,垃圾销毁时机。如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中。

  • 类似静态代码作用

    static{  	...  }  静态代码块在类加载的时刻执行,并且只执行一次  这是一个SUN准备的类加载时机.

注意:

  • java中的垃圾回收器不是轻易启动的垃圾太少,或者时间没到,种种条件下,有可能启动,也有可能不启动
public class Test06 {
public static void main(String[] args) {
/* //创建对象 Person p = new Person(); //怎么把Person对象变成垃圾? p = null; */ /* //多造点垃圾 for (int i = 0; i < 1000000; i++) { Person p = new Person(); p = null; } */ Person p = new Person(); p = null; //有一段代码可以建议垃圾回收器启动 System.gc(); //建议启动垃圾回收器,(只是建议,可能不启动,也可能不启动) }}//项目开发中有这样的需求:所以对象在JVM中被释放的时候,请记录一下时间//这个记录对象被释放的时间点,这个负责记录的代码就写在finalize方法中class Person{
//重写finalize //Person类型对象被垃圾回收器回收的时候,垃圾回收器负责调用:p.finalize(); @Override protected void finalize() throws Throwable {
System.out.println(this + "即将被销毁"); }}

5. 学习Object类中的hashCode()方法

hashCode()在Object中的源码:

public native int hashCode();不是抽象方法,带有native关键字,底层调用了底层的C++
  • hashCode()方法返回的是哈希码:实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值,所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址
public class Test07 {
public static void main(String[] args) {
Object o = new Object(); int hashCodeValue = o.hashCode(); //对象内存地址经过哈希算法转换的一个数字,可以等同看做内存地址 System.out.println(hashCodeValue); //1067040082 }}

三、内部类

1、内部类定义

在一个类的内部又定义了一个新的类,被称为内部类

  • 比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对于B类来说就是外部类了

一开始我们的写法是这样的。

在这里插入图片描述
注意:使用内部类编写的代码,可读性很差,能不用尽量不用

2、内部类分类

在这里插入图片描述

理解三种内部类

public class Test01 {
//静态变量 static String country; //该类在类的内部,所以称为内部类 //由于前面有static,所以称为"静态内部类" static class Inner1{
} //实例变量 int age; //该类在类的内部,所以称为内部类 //没有static叫做实例内部类 class Inner2{
} public void doSome(){
//局部变量 int i = 100; //该类在类的内部,所以称为内部类 //局部内部类 class Inner3{
} } public void doOther(){
//doSome()方法中的局部内部类Inner3在doOther()中不能用 //因为Inner3在doSome()方法中,方法一旦结束,里面的类也就没有了 }}

2.1 实例内部类

类似于实例变量

  • 创建实例内部类,外部类的实例必须已经创建
  • 实例内部类会持有外部类的引用
  • 实例内部类不能定义static成员,只能定义实例成员

在这里插入图片描述

2.2 静态内部类

类似于静态变量

  • 静态内部类不会持有外部的类的引用,创建时可以不用创建外部类
  • 静态内部类可以访问外部的静态变量,如果访问外部类的成员变量必须通过外部类的实例访问。
    在这里插入图片描述

2.3 局部内部类

类似于局部变量

  • 局部内部类是在方法中定义的,它只能在当前方法中使用。和局部变量的作用一样
  • 局部内部类和实例内部类一致,不能包含静态成员
    在这里插入图片描述

2.4 匿名内部类

  • 匿名内部类是局部内部类的一种
  • 因为该类没有名字而得名匿名内部类
    在这里插入图片描述
    注意:不建议使用匿名内部类
  • 因为一个类没有名字,没有办法重复使用,另外代码太乱,可读性太差
  • 学习匿名内部类主要目的是,为了以后在阅读别人代码的时候,能够理解,并不代表要这样写

转载地址:http://gqxzi.baihongyu.com/

你可能感兴趣的文章
L2-019. 悄悄关注
查看>>
POJ 3468 A Simple Problemwith Integers(SplayTree入门题)
查看>>
营业额统计 HYSBZ - 1588 (伸展树简单应用)
查看>>
HDU 1890 Robotic Sort(伸展树---反转应用)
查看>>
POJ 3580 SuperMemo(伸展树的几个基本操作)
查看>>
(十) Web与企业应用中的连接管理
查看>>
(八) 正则表达式
查看>>
一.JavaScript 基础
查看>>
7.ECMAScript 继承
查看>>
HTML DOM
查看>>
AJAX 基础
查看>>
JSON 基础
查看>>
J2EE监听器Listener接口大全[转]
查看>>
cookie、session、sessionid 与jsessionid[转]
查看>>
常见Oracle HINT的用法
查看>>
JAVA中各类CACHE机制实现的比较 [转]
查看>>
PL/SQL Developer技巧
查看>>
3-python之PyCharm如何新建项目
查看>>
15-python之while循环嵌套应用场景
查看>>
17-python之for循环
查看>>