Java中常用的语言类型

常用类

Object类

Object类在Java中的地位

Object类是Java语言中所有类的根,所有的类都直接或间接的继承了Object类; 数组也继承了Object类;

Object类中定义了11个方法,任何类都默认拥有(包括数组),可以使用API文档查询;本章学习其中4个方法;

equals与hashCode方法

Object类中定义了equals方法【 public boolean equals(Object obj) 】,用来比较两个对象的虚地址,如果虚地址相同则返回true,否则返回false;

Object类中的equals方法的作用,与==相同,都是比较两个对象的虚地址;

很多类覆盖了equals方法,用来比较两个对象的属性值,如果属性值相同,则认为两个对象相等;例如,String类就覆盖了equlas方法,用来比较两个字符串的字符序列值

c1和c2的属性值完全一样,但是返回false,不符合实际意义,怎么办呢?重写equals就行啦!API中很多类都重写了,例如String类。

Object类中定义了hashCode方法【 public int hashCode() 】,用来返回对象的哈希码;

hashCode方法主要为了配合基于哈希的集合类一起工作,例如HashSet、HashMap等【集合章节学习】;

默认情况下【即没有重新hashCode方法时】,当两个引用的虚地址相同时,hashCode返回相同的值,否则返回不同的值;

c1和c2的虚地址不同,所以hashCode返回不同的值;c2和c3的虚地址相同,所以hashCode返回相同的值。

事实上,基于哈希的集合在使用hashCode的时候,基本都是和equals一起使用;

基本流程如图:

既然使用的时候总是一起使用,那么重写的时候也一定要一起重写!!!hashCode和equals方法要一起重写,重写后的逻辑满足图中逻辑。

可以使用Eclipse的工具重写equals和hashCode方法;

toString()方法

字符串类型是编程时最常用的类型,Object类中定义了toString方法【 public String toString() 】,可以把任意类型对象转换成字符串返回;

默认情况(没有重写Object类中的toString方法)下,返回字符串的格式为:对象类型@对象调用hashCode方法的返回值;

两条打印输出语句输出结果相同,说明打印输出对象时,默认调用toString方法

Employee类中没有重写toString方法,所以使用的是Object中定义的方法,因此输出了这种“晦涩”的格式

返回Object类中默认格式的字符串几乎没有实用意义,因此很多时候,都会重写一些实体类的toString方法,返回需要的字符串格式;

Employee02类中重写toString方法,所以使用的是Employee02类中定义的方法,因此输出了自定义的格式。

不要学我使用Employee02这种带数字的命名格式啊~~此处完全为了演示方便。

clone()方法

Object类中定义了克隆方法clone 【protected Object clone() throws CloneNotSupportedException】;

Clone方法能够“复制”一个对象,生成一个新的引用,分配新的内存空间;

一个类必须实现Cloneable接口,才能被克隆,否则抛出异常;

输出为

s1==duoli: false

Alice 3

可见调用clone方法后,得到的对象duoli属性值和原来对象s1相同,但是却是一个新的引用地址,和直接用=赋值不同

克隆是生成了一个新的对象,然而,对象的属性如果有引用类型,实际上还是公用; 接上案例,加入如下两行代码;

可见,s1和duoli的name和age的值相同,但是,其中引用类型name实际上是一个引用,如下图所示:

通过前面,可见Object类中的clone方法默认是浅克隆;如果要实现深克隆,需要自行重写clone方法,如下所示:

在SheepDeepClone类中重写clone方法如下:

可见,深克隆时,s1和duoli的name和age不仅值相同,同时又都存储在完全不同的内存中,如下图所示:

克隆是用来创建对象的一种方式,当对象数据量比较大,变化又相对较少时,使用克隆能够一定程度减少产生对象的开销;

在一些面向对象的设计模式中使用克隆,实际项目开发中用得不多;

==操作符与equals方法

= =:

基本类型比较值:只要两个变量的值相等,即为true.

int a=5; if(a==6){…}

引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true.

用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错;

equals():所有类都继承了Object,也就获得了equals()方法。还可以重写。

只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象。

格式:obj1.equals(obj2)

特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;

原因:在这些类中重写了Object类的equals()方法。

练习

练习1

练习2

Scanner类

java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。 下面是创建 Scanner 对象的基本语法:

Scanner s = new Scanner(System.in);

接下来我们演示一个最简单的数据输入,并通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据:

使用 next 方法:

执行以上程序输出结果为:

可以看到 com 字符串并未输出,接下来我们看 nextLine。

使用 nextLine 方法:

执行以上程序输出结果为:

next() 与 nextLine() 区别

next():

一定要读取到有效字符后才可以结束输入。

对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。

只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。

next() 不能得到带有空格的字符串。

nextLine():

以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。

可以获得空白。

如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:

执行以上程序输出结果为:

以下实例我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果:

执行以上程序输出结果为:

String 类

在API中是这样描述:

String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。

字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。

String的构造方法

直接赋值方式创建对象是在方法区的常量池

通过构造方法创建字符串对象是在堆内存

两种实例的比较

常用方法

String的不可变性

String是个常量,从一出生就注定不可变.

String不可变的好处

可以实现多个变量引用堆内存中的同一个字符串实例,避免创建的开销。

我们的程序中大量使用了String字符串,有可能是出于安全性考虑。

大家都知道HashMap中key为String类型,如果可变将变的多么可怕。

当我们在传参的时候,使用不可变类不需要去考虑谁可能会修改其内部的值,如果使用可变类的话,可能需要每次记得重新拷贝出里面的值,性能会有一定的损失。

StringBuffer 类

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

主要方法:

其他很多方法和String相似

String类和StringBuffer类的区别

这两个类都实现了CharSequence接口。 1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用 2. String对象是不可变对象,不能修改值。而StringBuffer是可变对象,能修改值。 3. 拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。 4. String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。

System类

System类是一些与系统相关的属性和方法的集合,而且在System类中所有的属性都是静态的,要想引用这些属性和方法,直接使用System类调用即可。

public static void exit(int status) 系统退出 ,如果status为0就表示退出。

public static void gc() 运行垃圾收集机制,调用的是Runtime类中的gc方法。

public static long currentTimeMillis() 返回以毫秒为单位的当前时间。

public static void arraycopy(Object src,int srcPos, Object dest,int desPos,int length) 数组拷贝操作

public static Properties getProperties() 取得当前系统的全部属性。

public static String getProperty(String key) 根据键值取得属性的具体内容。

垃圾对象的回收

一个对象如果不使用,则肯定要等待进行垃圾收集,垃圾收集可以自动调用也可以手工调用,手工调用的时候就是调用System.gc()或者Runtime.getRuntime().gc()。但是,如果一个对象在回收之前需要做一些收尾工作,则就必须覆写Object类中的:

protected void finalize() throws Throwable

在对象被回收之前调用,以处理对象回收前的若干操作,例如释放资源等等。

System类本身提供的静态属性都是与IO操作有关的。在IO操作中还会有更多System类的使用,可以使用system类取得计算时间,以及通过gc()方法进行垃圾收集 此方法是包装了Runtime类中的gc()方法。

Math类

基本包装类

们知道,java提供的8种基本数据类型并不支持面向对象的编程机制,不具备“对象“的特性,没有成员变量、方法可以被调用。java之所以提供这8种基本数据类型,主要是为了照顾程序员的传统习惯。

这8种基本数据类型带来了一定的方便性,例如简单的数据运算和常规数据的处理。但是在某些时候,基本数据类型也会有一些制约,例如所有的引用类型的变量都继承了Object类,都可以当成Object类型变量使用。但基本数据类型的变量不可以,如果有方法需要Object类型的参数,但实际需要的值是1、2、3等数值,这可能就比较难以处理。

为了解决8中基本数据类型变量不能当成Object类型变量使用的问题,java提供了包装类的思想,为8种基本数据类型分别定义了相应的引用类型,并称之为基本数据类型的包装类。

基本数据类型和包装类的对应表

除了int和char之外,其他的基本数据类型只需要首字母大写即可编程它们对应的包装类。

自动装箱和自动拆箱:

我们都知道,不可以直接把基本数据类型赋值给引用数据类型。所以在JDK1.5之前,构建一个包装类需要通过构造器来构造包装类对象,但是这显得代码过于麻烦,所以从1.5之后就提供了自动装箱和自动拆箱的功能。

自动装箱:就是可以把一个基本类型变量直接赋值给对应的包装类变量,或者赋值给Object变量(因为Object类是所有类的父类);

自动拆箱:与自动装箱相反,允许直接把包装类对象直接赋值给一个对应的基本类型变量。

当JDK提供了自动装箱和自动拆箱功能后,大大简化了基本类型变量和包装类对象之间的转换,值得提出的是,进行自动装箱和自动拆箱时,必须注意类型匹配,例如Integer只能自动拆箱成int类型变量,不要试图拆箱成boolean类型变量;与之类似的是,int类型只能自动装箱成Integer对象,即便赋给Object类型变量,那也是利用了自动转型的特性,不要试图将int自动装箱成Boolean类型对象。

借助这种机制,一定程度上,我们可以把包装类当成基本数据类型使用,也可以把基本类型的变量近似的当成对象使用(当然,使用的时候需要自动装箱一下)。

除此之外,包装类还可以实现基本类型变量和字符串之间的转换,把字符串类型的值转换为基本类型的值有两种方式。

parseXxx(String )静态方法。(Character除外)

利用包装类提供的Xxx(Stirng s)构造器。

String类型也提供了多个重载的valueOf()方法,用于将基本类型变量转换成字符串,下面程序示范 了这种转换关系。

当包装类型的变量是引用数据类型,但是我们也可以拿这些包装类型对象与数值类型的值比较,这种比较是直接取出包装类的实例所包装的数值再与之进行比较。

但是,如果是两个包装类型直接比较,即便包装的值相同,但是也会返回false,因为引用数据类型比较是有其他方式比较的,以后会说引用数据类型的比较。

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180503G0S1IR00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券