一 API的使用和常用包的概述
前言
对包的概念,我们在前面其实给大家提过,实际上说白了,是不是就是目录的意思 对不对哎?也就是说,实际上就是JAVA官方提供了很多个目录。
那为什么要有目录啊?讲过吧,目录的目的是为了什么来着?是为了便于管理,而且解决同名的问题。
包=目录
1 常用的包(熟悉)
1.1 包的名称和功能
(1)java.lang包 - 该包是Java语言的核心包,并且该包中的所有内容由Java虚拟机自动导入。 如:System类、String类、...
疑问:
大家会发现我们虽然使用,但从来没有说写过代码儿,说import java.lang.system,或者说import java.lang.string从来没有写过吧。知道为什么吗?哎,答案就在这里,已经给大家标的很清楚了,说这个包中的类是由什么来着?是由JAVA虚拟机自动导入。
(2)java.util包 - 该包是Java语言的工具包,里面提供了大量工具类以及集合类等。 如:Scanner类、Random类、List集合、...
(3)java.io包 - 该包是Java语言中的输入输出包,里面提供了大量读写文件相关的类等。 如:FileInputStream类、FileOutputStream类、...
介绍:IO呢,实际上就是input output这个单词的,这俩单词的简写。输入输出怎么理解?其实就是读写的意思,也就是说学完这个包里面的相关的类之后啊,我们可以干嘛呢?我们可以对文件中的内容进行读写,甚至对文件之间进行拷贝。
对前几个包进行一个小总结:
这个lang包是最基本的包,基本上写JAVA代码离不开,然后学完util包之后,我们可以用各种工具类,还有集合。或者说叫把它叫做容器,有容器可以装数据;好学完IO之后,我们就可以对文件的内容进行读写?
(4)java.net包 - 该包是Java语言中的网络包,里面提供了大量网络编程相关的类等。 如:ServerSocket类、Socket类、...
介绍:
所谓的网络编程怎么理解啊?其实说白了,就是说哎,学完这个网络包之后,如你跟你室友或者说你跟你同桌,你们俩之间可以通过自己写的代码啊,然后通过网络,通过这个局域网就可以进行通信了。明白了吧,说的再俗一点儿,就是说你在你的电脑上把程序启动起来,给你同桌的电脑上,或者说你室友的电脑上发一个消息,比如说在吗?明白这意思吧。
(5)java.sql 包 - 该包是Java语言中的数据包,里面提供了大量操作数据库的类和接口等。 如:DriverManager类、Connection接口.....
介绍:
实际上是数据包是跟数据库有关的,那这个包虽然属于java SE的内容,但java SE的课程里面我是不会讲的,为什么呢?因为这是用来操作数据库的嘛,我们不学数据库的话。学这个包也没啥价值。明白了吧,所以这个包呢,会甩到后边儿.
(6)Java程序员在编程时可以使用大量类库,因此Java编程时需要记的很多,对编程能力本身要求不是 特别的高。
也就是说接下来咱们核心内库这一块内容的学习怎么学呢?
我们基本上是先介绍lang包,然后介绍Util包,然后回去再浪一圈儿,然后介绍IO包,然后回去再浪一圈儿,然后介绍net包,然后再去浪一圈儿,然后浪着浪着。se的核心类库就写完了。明白这意思了吧?哎,就是这么一个理念。
2 Object类的概述(重点)
2.1 基本概念
(1)java.lang.Object类是Java语言中类层次结构的根类,也就是说任何一个类都是该类的直接或者间接子类。
(2)如果定义一个Java类时没有使用extends关键字声明其父类,则其父类为 java.lang.Object 类。
(3)Object类定义了“对象”的基本行为, 被子类默认继承。
2.2 常用的方法
2.2.1 Object()方法
分析:
2.2.2 equals()方法
(1)大家观察一下这个方法呢,有没有static关键字?修饰呢没有吧,那没有static关键字修饰,那意味着这个方法应该隶属于对象层级,是得需要对象点儿去调用
(2)另外这个方法的话呢,有一个参数是object类型的obj。对不对?它需要一个参数。诶,注意啊,这个参数是object类型的obj。而object类型,我们刚刚讲了,它是所有类的根类,任何类往上找父类,最终一层一层的找,最终是不是都会找到object类。而这个方法的形参类型就用的是object类。觉得这有什么问题吗?诶,没什么问题,但这样设计非常巧妙。这怎么说呀?别忘了我们前面给大家讲过什么叫多态啊?当父类类型的引用指向子类类型的对象时,我们就叫做多态。有印象吧哎,这就叫多态,而现在我让object类型的变量作为形参往这儿一站,那就意味着而object又是所有类的根类,那就意味着我们调用equals方法时,实参是可以随便传。对吧,实参你就随便传呗。只要是个对象,是不是都可以传,因为大不了我就形成多态呗。所以这个手法是很巧妙的一个手法,大家一定要留意,我们在以后的开发中,我们要经常用到这个手法。
(3)另外这个方法的返回值是布尔类型,那布尔类型什么意思啊?就是是否呗。
(4)在代码中的使用,这个是其中的一个Student类,还有一个是测试类(图片中的红色的字是我不太懂我框的那部分的意思,进行了解释)
测试类
解释一下代码的执行流程(下面这张图中就是代码,我们要了解流程的代码)
图示的流程就是这样
下面这张图是我们在执行到boolean b1=s1.equal(s2),跳转到的代码。
this代表调用对象;obj代表参数对象
至此,代码已经执行完毕。
2.2.3 equals方法的一些特性
接下来我们再了解一下equals方法的一些特性。
前提:equals方法在非null对象引用上实现等价关系
提问:为什么要强调非空对象?
因为空引用调用方法就会引发空指针异常。
(1)自反性:对于任何的非空的参考值x,x.equals(x)应该返回true。
(2)它是对称的:对于任何非空引用值x和y,x.equals(y)应该返回true,当且仅当y.equals(x)回报true。
简单来说就是x和y相等,那y和x也相等。
(3)传递性:对于任何非空引用值x,y和z,如果x.equals(y)回报true个y.equals(z)回报给true,然后x.equals(z)应该返回true.
简单来说就是x和y相等,y和z相等,那x和z也是相等的。
(4) 一致性:对于任何非空引用值x和y,多次调用x.equals(y)始终返回true或始终返回false,前提是未修改对象上的equals比较中使用的信息。
比较的信息没改也就说明那比较的结果自然没改。
(5)对于任何的非空的参考值x,x.equals(null)应该返回false。
下面这两张图是想要说明 当调用对象不为空,而参数对象为空时,则内容一定不同
下面三张图是为了说明 当调用对象和参数对象指向同一个对象时,则内容一定相同。
2.2.4 hashCode方法的重写实现
请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定;该方法声明相等对象必须具有相等的哈希代码。
返回调用对象的哈希码值(内存地址的编号)
分析:hashCode方法和equals方法应该保持一致
分析:大家可以想象一下,就是我们刚说了,你把那个哈希码值想象成内存地址的编号。那你想想,如果两个对象调equals相等。而equals的默认比较俩对象地址嘛,对不对?那你想想,如果两个对象调用equals相等,不就说明两个对象的。什么来着?内存地址相同吗?而hashCode方法得到的是内存地址的编号,所以也就相同。
下面的代码是对hashCode方法在代码中的详细使用
运行结果:
2.2.4.1 怎么写代码才能过避免违背java官方的协定
那怎么写代码才能过避免违背java官方的协定呢?
在代码中体现,一步一步的来理解
为了满足java中的常规规范,我们需要对hashMap进行重写,重写的目的是为了让它跟equals方法保持一致.
我现在要求要做到的是equals相等hashcode就要相同;equals不相等hashcode就要不同。(这个就是java官方的规范)
那怎么做到这一点啊?诶,那就得要分析equals相等不相等取决于什么,我们看equals的代码。equals判断,两个对象是否相等,特殊情况除外,那最核心的理念实际上是不是就是判断学号是否相同。对吧,也就是说学号相同的时候equals的结果就相等呗,学号不同的时候equals的结果是不是就不同啊?好,那我现在hashcode要想跟equals的保持一致,怎么做来着?我只需要让我hash code是不是也依赖于学号就行了。对吧哎,你看你equals是不是相对依赖于学号,那我hashCode的结果如果也依赖于学号的话,那意味着咱俩不就保持一致了吗?因为我们都依赖于同一个内容嘛。
2.2.5 toString()方法
分析:tostring就是字符串儿呗,对不对?然后这个方法名儿呢?叫tostring,然后小括号里面什么都没有,说明这个方法不需要任何的参数返回值string类型对不对?
运行结果:
toString方法的一个特例(使用print或println打印引用或字符串的拼接引用都会自动调用该方法)
运行结果:
2.2.6 案例题目
编程实现Student类的封装,特征:学号(id)和姓名,要求提供打印所有特征的方法。 编程实现StudentTest类,在main方法中使用有参方式构造两个Student类型的对象并打印特征。
package com.lagou.task3;
public class Student extends Object {
private int id;//用于描述学员的成员变量
private String name;//用于描述姓名的成员变量
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if(id>0){
this.id = id;
}else{
System.out.println("学号不合理哦!!!");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*
为了比较两个对象的内容,也就是学号信息需要重写该方法
*/
@Override
public boolean equals(Object obj){
//当调用对象和参数对象指向同一个对象时,则内容一定相同
if(this==obj) return true;
//当调用对象不为空而参数对象为空时,则内容一定不相同
if(null==obj) return false;
//判断obj指向的对象是否为Student类型的对象,若是条件成立,否则条件不成立
if(obj instanceof Student){
Student ts=(Student) obj;
return this.getId()==ts.getId();
}
//否则类型不一致没有可比性,则内容一定不相同
return false;
}
/*
* 为了使得该方法的结果与equals方法的结果保持一致,从而满足java官方的常规协定,需要重写该方法
*
* */
@Override
public int hashCode(){
final int type=12;
return type*31+getId();
}
/**
* 为了返回更有意义的字符串数据,则需要重写该方法
*/
@Override
public String toString(){
return "Student[id=" +getId()+ ",name=" + getName()+ "]";
}
}
package com.lagou.task3;
public class StudentTest {
public static void main(String[] args) {
//1.使用有参方式构造Student类型的两个对象并判断是否相等
Student s1=new Student(1001,"zhangfei");
Student s2=new Student(1002,"liming");
boolean b1=s1.equals(s2);
System.out.println("b1="+b1);
//当Student类中重写toString方法后,则调用重写以后的版本
String str1=s1.toString();
System.out.println("str1="+str1);
String str2=s2.toString();
System.out.println("str2="+str2);
}
}
运行结果:
题目扩展: 如何实现以姓名作为基准判断两个对象是否相等?以及以学号和姓名同时作为基准判断两个对象是 否相等?
解释一下这样写错误的原因:
我并不是说判断这两个学生的姓名是否是一个地址吧。不是这样判断的吧,而只需要判断它们这两个字符串儿,这个姓名的内容是否相同吧,比如说你叫张飞,他也叫张飞,张飞都是张飞。内容相同,是不就认为是同一个人?对不对?也就是再看下图,也就是说我并不是看的是这里面的地址是否相同,我并不是比较这俩,我是不是应该比较它们在内存空间中的具体的内容是否相同。
正确的写法:
在Student类中只对equals方法修改了一段代码
在Student类中只对hashCode方法修改了一段代码:
toString方法就不用改变了,因为他打印的是Student的特征 。
修改这两个方法之后运行结果也能够正常输出:
2.2.7 我们用ideal自动生成的equals方法和hashCode方法(alt+shift+insert)
2.2.7.1 方式一
步骤:
然后一路next就可以
下面这张图是用ideal自动生成的hashCode方法
2.2.7.2 方式二
步骤:
然后一直按next就可以了
toString方法也可以自动生成,方法和上面的差不多,先按快捷键+选toString()+一路next 。
总结: