1、System
1.1、System类的特点
System 类包含一些有用的类字段和方法。它不能被实例化。(不能被实例化说明其美元构造函数,因此System里面的成员全部为静态)
在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
1.2、System的常用方法
System的系统信息获取
/*
System:类中的方法和属性都是静态的。
out:标准输出,默认是控制台。
in:标准输入,默认是键盘。
*/
package pack;
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
//System是系统类,它可以描述系统环境,系统环境在虚拟机启动的时候会加载一些默认的系统启动信息,可以通过getProperties()查阅当前系统属性。
//获取系统属性信息:public static Properties getProperties(),它返回Properties类对象
Properties prop = System.getProperties();
/*
* 因为Properties是Hashtable的子类,也就是Map集合的一个子类对象。那么可以通过map的方法取出该集合中的元素。(将其看做一个map集合即可)
* 该集合prop中存储都是字符串,没有定义泛型。(也就是Properties类没有定义泛型,因此在获取prop的Set集合时(既获取prop的键),也不能定义泛型)
*/
//利用foreach获取所有属性信息
Set keySet = prop.keySet();//获取prop(Map)集合的键的集合(此处没有定义泛型)
for(Object obj : keySet)//我们在此处没有添加泛型,因此必须用Object表示,以兼容所有类型
{//获取Object类型的值,并向下强转为String(prop虽然不能定义泛型,但是他的全部值都是String类型)
String value = (String)prop.get(obj);//获取prop集合的值并装换为String类型
System.out.println(obj+"---"+value);
}
}
}
/*
结果:(信息分析见18-1,10分钟开始处)
如果在其他电脑上运行这段程序,会出现不一样的结果!
*/
System关于系统信息的其他功能
package pack;
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
//如何在系统中自定义一些特有信息呢?
System.setProperty("myKey", "myValues");//结果系统信息中出现了:myKey---myValues
Properties prop = System.getProperties();
Set keySet = prop.keySet();
for(Object obj : keySet)
{
String value = (String)prop.get(obj);
System.out.println(obj+"---"+value);
}
//获取单个属性
String value = prop.getProperty("os.name");
System.out.println("value="+value);//value=Windows 10
//可不可以在jvm启动时,动态加载一些属性信息呢?(18-01,21)
//我们可以在编译的时候通过命令行的命令来动态设置。
String v = System.getProperty("haha");
System.out.println("v="+v);
}
}
对于上面所述的最后一个动态添加属性信息的示例,我们在pack包下面,使用命令行,可以编译,但是没办法运行,因为代码中指定了包,我们在编译的时候必须指定包要存放的位置!
我们在编译的时候指定包存放在当前目录下,在运行的时候注意加上包名,这样便正常运行。同时,在当前目录下,有一个存放SystemDemo.java的包pack存在。
同时,我们发现,如果我们退pack文件夹,再在pack文件夹外面使用java pack.SystemDemo命令,就可以正常运行。
我们再创建一个SystemDemo类,但是我们不使用包来封装这个类,我们直接编译,发现正常运行。
如果我们在上面的SystemDemo.java中加入package pack包,如下:
综上所述,如果我们的代码里面指定了包来封装当前的类,那么我们,在命令行编译的时候必须指定包含“.class”的包所存放的位置,然后在运行的时候用“java 包名.类名”来运行,不可以进入包中用“java 类名”进行直接运行,这样会出错,因为包和“.class”文件是一个整体。
另外,像向第一个例子,我们的SystemDemo.java文件已经存放在pack包下,编译生成的SystemDemo.class也在pack下,但是由于代码指定了包名,因此在运行的时候需要退出pack,在pack外面用“java pack.SystemDemo”来运行。
总而言之,带有包名的类在编译时指定包存放位置,在运行的时候在包外用“java 包名.类名”来运行就不会出错。
System的arraycopy()方法
/*
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。
参数:
src - 源数组。
srcPos - 源数组中的起始位置(起始索引)。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量。
练习:
将src数组中前3个元素,复制到dest数组的前3个位置上
复制元素前:
src数组元素[1,2,3,4,5],dest数组元素[6,7,8,9,10]
复制元素后:
src数组元素[1,2,3,4,5],dest数组元素[1,2,3,9,10]
*/
private static void demo02() {
//定义源数组
int[] src = {1,2,3,4,5};
//定义目标数组
int[] dest = {6,7,8,9,10};
System.out.println("复制前:"+ Arrays.toString(dest));
//使用System类中的arraycopy把源数组的前3个元素复制到目标数组的前3个位置上
System.arraycopy(src,0,dest,0,3);
System.out.println("复制后:"+ Arrays.toString(dest));
//注意复制的内容会将目标数组的相应位置的内容覆盖!
}
2、Runtime
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。(见18-02,0.20处解析)
Runtime并没有提供构造函数,说明不可以new对象,那么会直接想到该类中的方法都是静态的,但是我们发现该类中还有非静态方法。这说明该类肯定会提供了方法获取本类对象,而且该方法是静态的,并返回值类型是本类类型。由这个特点可以看出该类使用了单例设计模式完成。该方式是static Runtime getRuntime();
- public static Runtime getRuntime():返回与当前 Java 应用程序相关的运行时对象,该对象不需要我们创建,应用程序本身就创建完毕,我们只需要获取使用即可。Runtime 类的大多数方法是实例方法,并且必须根据当前的运行时对象对其进行调用。
代码示例:
package pack;
import java.io.IOException;
class RuntimeDemo
{
//注意抛出IO异常的导入相应的包,抛出sleep的InterruptedException
public static void main(String[] args) throws IOException , InterruptedException
{
Runtime r = Runtime.getRuntime();//创建一个与应用程序相关的运行对象
//exec(String command):在单独的进程中执行指定的字符串命令。(18-02,7.00)
//我们有可能传错数据,这样会抛出异常,且exec方法也会抛出IOException,那么我们这里在方法处手动抛出异常。
r.exec("G:\\write.exe");//我们在该目录下放入写字板的执行文件,执行这段代码就会运行写字板
//我们不指定执行文件的目录,仍然可以执行。(18-02,10.40)
//如果在当前目录下找不到或者没有当前目录,就会到path设置的系统目录下面找,找不到就运行失败!
r.exec("write.exe");
//示例:这里“\”是转义字符,如\Program会将P转义,就是“\p”,这样没有意义,那么我们再加一个“\”吗,表示为“\\”,这就是普通的“\”目录封装符
r.exec("C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQ.exe");//打开了qq
/*
* process类(18-02,13.00): Runtime.exec 方法创建一个本机进程,并返回 Process子类的一个实例,该实例可用来控制进程并获得相关信息。
* process类是抽象的,它的方法也是抽象的,但是没有实现process的子类。因为应用程序一被执行,就已经产生进程,这个进程是调用底层资源创建的,
* 因此我们只定义抽象类Process而不定义实现Process的子类,因为底层在做Process的实现,不需要我们来实现。
*/
//destroy():杀掉子进程。
Process p = r.exec("C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQ.exe");
Thread.sleep(4000);//使用Thread的sleep()方法让线程等一下,注意抛出InterruptedException
p.destroy();//清除p所指定的子线程
//我们只能操作p所指定的进程,其他进程无法操作
//用记事本文件打开SystemDemo.java文件。只要是记事本可以打开的文件,就都可以用这个命令打开。
//在eclipse中,这个文件必须放置Test项目文件夹下,系统才能找到。路径:F:\研究生学习资料\java\eclipse\eclipse\workspace\Test
Process p1 = r.exec("notepad.exe SystemDemo.java");
}
}
3、Date工具类
Date工具类在java.util包中,使用前需先导入util包。类 Date 表示特定的瞬间,精确到毫秒。 从 JDK 1.1 开始,应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串。Date 中的相应方法已废弃。
代码示例
package pack;
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args) throws ParseException
{
//先将时间转换为文本
Date d = new Date();
System.out.println(d);//Thu Sep 19 02:17:57 CST 2019:格式较为复杂
//将我们想设置的简单的模式封装到SimpleDateformat对象中。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E hh:mm:ss");//这里y\M\d只要有一个出现就会显示
String time = sdf.format(d);//使用SimpleDateFormat的format方法将给定的 Date对象格式化为指定的日期/时间字符串
System.out.println("time:"+time);
//Date的另一种初始化方法:Date(long date)
long l = System.currentTimeMillis();
Date d1 = new Date(l);
System.out.println("d1:"+d1);
//以上是将时间转换为文本,下面我们将文本转换为时间
//1.创建SimpleDateFormat对象,构造方法中传递指定的模式
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
//2.调用SimpleDateFormat对象中的方法parse,把符合构造方法中模式的字符串,解析为Date日期
//Date parse(String source) 把符合模式的字符串,解析为Date日期
Date date = sdf1.parse("2088年08月08日 15时51分54秒");
System.out.println(date);
}
}
日期与毫秒之间的转换
把日期转换为毫秒:
当前的日期:2088-01-01
时间原点(0毫秒):1970 年 1 月 1 日 00:00:00(英国格林威治)
就是计算当前日期到时间原点之间一共经历了多少毫秒 (3742767540068L)
注意:
中国属于东八区,会把时间增加8个小时
1970 年 1 月 1 日 08:00:00
把毫秒转换为日期:
1 天 = 24 × 60 × 60 = 86400 秒 = 86400 x 1000 = 86400000毫秒
4、Calendar工具类
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
Calendar示例1:注意Calendar获取的都是数字
package pack;
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
/*
//如果我们单单想获得年
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
System.out.println("年:"+sdf.format(d));//年:2019
//这里获得的年是字符串,我们可以用Integer的parseInt转换为int类型
*/
//static Calendar getInstance():Calendar是抽象类,不能直接实例化,
//只能使用getInstance()方法获取Calendar子类GregorianCalendar的实例
Calendar c = Calendar.getInstance();
System.out.println(c);
//分析:(18-04,8.00):打印了一堆信息。发现返回GregorianCalendar对象,也就是getInstance()返回Calendar的子类GregorianCalendar的对象
System.out.print(c.get(Calendar.YEAR)+"年");
System.out.print((c.get(Calendar.MONTH)+1)+"月");//月份用0-11表示,使用的时候+1
System.out.print(c.get(Calendar.DAY_OF_MONTH)+"日");
System.out.println(" 星期"+(c.get(Calendar.DAY_OF_WEEK)-1));//这里星期天对应数字1,表示出来是星期0
//2019年8月19日 星期4——系统月份从0开始——调整(月+1):2019年9月19日 星期4——很麻烦,而且不好看,且星期几不好表示
//使用查表法
String[] mons = {"一月","二月","三月","四月",
"五月","六月","七月","八月",
"九月","十月","十一月","十二月"};//注意月份从0-11,刚刚好对应数组下标。
String[] weeks = {
"星期日","星期一","星期二","星期三","星期四","星期五","星期六",
};//1-7对应周日到周六,且数组下标从0开始,将星期天放在数组开始,并且表示的时候应该-1
//我们先获取月日对应的数字,再拿去查表
int monthIndex = c.get(Calendar.MONTH);
int weekIndex = c.get(Calendar.DAY_OF_WEEK);
System.out.println(mons[monthIndex]);//九月:这样就好看很多。
System.out.println(weeks[weekIndex-1]);
}
}
Calendar示例2
package pack;
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
//如果想对c进行重新的时间设定,可以使用set()方法
// c.set(2020,6,6);//这里set设置月份也是从0-11,6代表7月
// printCalendar(c);//2020年七月6日:星期一
//add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
// c.add(Calendar.YEAR, -8);//当前年减去8年
// printCalendar(c);//2011年九月19日:星期一
c.add(Calendar.MONTH, 3);
printCalendar(c);
}
//设置一个专门打印Calendar的方法
public static void printCalendar(Calendar c)
{
String[] mons = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[] weeks = {
"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",
};
int index = c.get(Calendar.MONTH);//获取月
int index1 = c.get(Calendar.DAY_OF_WEEK);//获取周
System.out.print(c.get(Calendar.YEAR)+"年");
System.out.print(mons[index]);
System.out.print(c.get(Calendar.DAY_OF_MONTH)+"日"+":");
System.out.print(weeks[index1]);
}
}
Calendar练习
/*
三个练习:
1,获取任意年的二月有多少天。
思路:根据指定年设置一个时间就是 :c.set(year,2,1)//某一年的3月1日。
c.add(Calenar.DAY_OF_MONTH,-1);//3月1日,往前推一天,就是2月最后一天。
2,获取昨天的现在这个时刻:c.add(Calenar.DAY_OF_MONTH,-1);
3,求一段时间内的有效天数——如从6月6日到8月18日培训,周六日不上课,求期间上课的有效天数
*/
package pack;
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
//获取某一年2月份天数
// System.out.print("2019年2月份天数为:");
// getFebDays(c,2019);
//获取昨天这个时刻
getYesTime(c);
//昨天是18日 4时47分14秒
//求一段时间内的有效天数——如从6月6日到7月18日培训,周六日不上课,求期间上课的有效天数
getClassDays(c);
}
//求一段时间内的有效天数——如从6月6日到7月18日培训,周六日不上课,求期间上课的有效天数
public static void getClassDays(Calendar c)
{
c.set(2019,6,18);
int lastDay = c.get(Calendar.DAY_OF_MONTH);
int lastMonth = c.get(Calendar.MONTH);//获取最后一天的日与月
c.set(2019,5,6);//将日期设置为最开始的那天
int dayNum = 0;
//如果月份与日期对不上,就将日期加一
for(;!(c.get(Calendar.MONTH)==lastMonth && c.get(Calendar.DAY_OF_MONTH)==lastDay) ; c.add(Calendar.DAY_OF_MONTH, 1) )
{
//如果日期在逐渐+1的过程中,不是星期六与星期天,就将计算天数+1
if(!(c.get(Calendar.DAY_OF_WEEK)==1) && !(c.get(Calendar.DAY_OF_WEEK)==7))
dayNum++;
}
System.out.println("上课的天数为:"+dayNum);//上课的天数为:30。正确
}
//获取昨天这个时刻的方法
public static void getYesTime(Calendar c)
{
c.add(Calendar.DAY_OF_MONTH, -1);//直接将当前天数-1
System.out.println("昨天是"+c.get(Calendar.DAY_OF_MONTH)+"日");
System.out.println(c.get(Calendar.HOUR_OF_DAY)+"时"+c.get(Calendar.MINUTE)+"分"+c.get(Calendar.SECOND)+"秒");//获取昨天这个时刻
}
//获取某一年2月天数的方法
public static void getFebDays(Calendar c, int year)
{
//先设置某一年的3月1日(注意月份从0-11)
c.set(year,2,1);
c.add(Calendar.DAY_OF_MONTH, -1);//3月1日,往前推一天,就是2月最后一天,也就是2月份的天数
System.out.println(c.get(Calendar.DAY_OF_MONTH));//获取2月份最后一天,也就是这一年2月份天数
}
//设置一个专门打印Calendar的方法
public static void printCalendar(Calendar c)
{
String[] mons = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[] weeks = {
"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",
};
int index = c.get(Calendar.MONTH);//获取月
int index1 = c.get(Calendar.DAY_OF_WEEK);//获取周
System.out.print(c.get(Calendar.YEAR)+"年");
System.out.print(mons[index]);
System.out.print(c.get(Calendar.DAY_OF_MONTH)+"日"+":");
System.out.print(weeks[index1]);
}
}
6、Math类与Random类
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。 Math中的成员都是静态的。示例如下:
package pack;
import java.util.*;
class DateDemo
{
public static void main(String[] args)
{
showRandom();
}
public static void show()
{
//static double ceil(double a) 返回大于a值的最小的double类型的整数。
double d = Math.ceil(12.567);
System.out.println(d);//13.0
double d1 = Math.ceil(-12.567);
System.out.println(d1);//-12.0
//static double floor(double a) 返回小于a值的最大double类型的整数
double d2 = Math.floor(12.567);
System.out.println(d2);//12.0
double d3 = Math.floor(-12.567);
System.out.println(d3);//-13.0
//static long/int round(double a) :四舍五入
int r = Math.round(12.56f);
System.out.println(r);//13
long r1 = Math.round(12.46);
System.out.println(r1);//12
//static double pow(double a, double b) :幂运算
double db = Math.pow(2, 3);
System.out.println(db);//2^3=8.0
}
public static void showrandom()
{
//static double random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。
for(int x=0; x<10 ;x++)
{
double d = Math.random();
System.out.println(d);//打印10个double类型的0.0-1.0的随机数
}
//打印1-10之间的随机数
for(int x=0; x<10 ;x++)
{
int i = (int)(Math.random()*10+1);//1<=Math.random()*10+1<11,强转为int后为1-10
System.out.println(i);//打印10个double类型的0.0-1.0的随机数
}
}
public static void showRandom()
{
Random r = new Random();
for(int x=0; x<10 ;x++)
{
//int nextInt(int n) 返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
int i = r.nextInt(10)+1;//返回1-11(不包含11)之间的随机整数
System.out.println(i);
}
}
}
Math练习
/*
练习:给定一个小数,保留该小数的后两位。
可以考虑,保留时进行四舍五入,或者不进行四舍五入直接保留。
*/
package pack;
import java.util.*;
class DateDemo
{
public static void main(String[] args)
{
saveTwo(12.56678,2,true);//四舍五入:12.57
saveTwo(12.56678,2,false);//不四舍五入:12.56
}
//double为要保留的数,scale为要保留的小数位数,isRound表示是否需要四舍五入
public static void saveTwo(double num, int scale, boolean isRound)
{
double base = Math.pow(10, scale);
//需要四舍五入就先乘以base,四舍五入后为整数再除以base;不需要四舍五入就直接乘以base,int强制取整,再除以base
double number = isRound?Math.round(num*base)/base:((int)(num*base))/base;
System.out.println(number);
}
}
7、Object类
理论上Object类是所有类的父类,即所有类都直接或间接的继承java.lang.Object类。由于所有的类都继承在Object类,因此省略了extends Object关键字。Object中定义的方法是所有对象都具备的方法!
该类中主要有以下方法: toString()、getClass()、equals()、clone()、finalize()、hashCode()、notify()、notifyAll()、wait()。 其中toString(),getClass(),equals()是其中最重要的方法。
Object类中的getClass()、notify()、notifyAll()、wait()等方法被定义为final类型,因此不能重写。
下面我们说一下Object类中的几个方法。参考如下文章
添加链接描述
7.1、equals()方法
java认为所有的对象都具备比较性,都能比较2个对象是否相同。
equals(Object obj) ,这里使用了多态的特性!!!
public boolean equals(Object obj)
{
return this == obj;
}
Object中的equals方法是直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象。所谓同一对象就是指内存中同一块存储单元,如果this和obj指向的同一块存储单元,则返回true,如果this和obj指向的不是同一块内存,则返回false。
注意:即便是内容完全相等的两块不同的内存对象,也返回false。如果希望不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equal方法,String类已经重写了object中的equals方法(这样就是比较内容是否相等了)。
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo();
Demo d3 = d1;
//false,因为2个不同的对象会在堆内存中开辟2个不同区域
System.out.println(d1.equals(d2));
//true,因为d1与d3是同一个对象,同一个内存地址!!!
System.out.println(d1.equals(d3));
}
}
class Demo{}
我们可能有比较内存不同但内容不知道是否相同的2个对象。如下:
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo(3);
Demo d2 = new Demo(4);
//用于比较对象的内容是否相同
System.out.println(d1.compare(d2));
}
}
class Demo
{
private int num;
public Demo(int num)
{
this.num = num;
}
//用compare方法比较Demo2个对象的num值是否相同
public boolean compare(Demo d)
{
return this.num == d.num;
}
}
如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有比较内容即可,这就是覆盖(重写)。比如如果希望比较不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equal方法,如下:
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo(3);
Demo d2 = new Demo(4);
//用于比较对象的内容是否相同
System.out.println(d1.equals(d2));
//对于另一个类的对象,如果我们不在重写的equals方法中比较,会出错
Person p = new Person(3);
System.out.println(d1.equals(p));
//结果:2个对象不属于同类 false
}
}
class Demo
{
private int num;
public Demo(int num)
{
this.num = num;
}
//我们重写equals方法来比较内容
public boolean equals(Object obj)//Object obj = d2
{
//此处使用多态,obj是Object类的引用,不可以直接使用Demo的私有变量num
// return this.num == obj.num;
/*
//增加一个判断,传递的参数obj如果是this本身,直接返回true,提高程序的效率
if(obj==this){
return true;
}
//增加一个判断,传递的参数obj如果是null,直接返回false,提高程序的效率
if(obj==null){
return false;
}
*/
//编译器重写格式如下
@Override
public boolean equals(Object o) {
if (this == o) return true;
//getClass() != o.getClass() 使用反射技术,判断o是否是Person类型 等效于 obj instanceof Person
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
//我们使用向下类型转换就可以调用子类特有的内容
if(obj instanceof Demo)
{
Demo d = (Demo)obj;
return this.num == d.num;
}else {//如果我们传入的对象不是Demo类型,内容肯定不同(就算数字相同,但是对象不同内容必然不同)
System.out.println("2个对象不属于同类");
return false;
}
}
}
class Person
{
private int num;
public Person(int num)
{
this.num = num;
}
}
这里使用到了java.util.Objects
类,那么这个类是什么呢?
在JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。
在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。方法如下:
public static boolean equals(Object a, Object b)
:判断两个对象是否相等。
我们可以查看一下源码,学习一下:
public static boolean equals(Object a, Object b) {
//这里如果a,b有一个为空,或者a,b地址值不相同,就会判断“a == b”,返回flase,那么后面一句比如也是false;如果a,b地址值相同,直接返回true;在a,b不为空且地址值不同的时候,再判断他们的内容是否相同。
return (a == b) || (a != null && a.equals(b));
}
7.2、toString()方法
java认为所有对象都能转换为字符串被打印
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。该方法用得比较多,一般子类都有覆盖。
public String tostring()
{
return getClass(). getName()+"@"+Integer. toHexstring (hashCode());//其实getClass()与hashCode()方法前面都应该加一个this表示当前对象
}
例子如下
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo();
System.out.println(d1.toString());
}
}
class Demo{}
7.3、hashCode()方法
public int hashCode()
返回该对象的哈希码值
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo();
System.out.println(d1.toString());
System.out.println(Integer.toHexString(d1.hashCode()));
}
}
class Demo{}
//结果
Demo@7852e922
7852e922
7.4、getClass()方法
public final Class getClass()//返回类名,返回值是Class类,比较特殊
//Class类用于描述class文件,就是***.class文件。
返回次Object的运行时类类型。不可重写,要调用的话,一般和getName()联合使用,如getClass().getName()。(这一部分具体见8.9第6分钟开始的分析,目前比较难理解)
这其中又涉及getName()方法,这个方法以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo();
//返回d1所对应的Demo类类型,将这个Demo类型赋予Class类的对象c;
//因为Class类本来就是用来描述类文件“.class”文件的,此时c代表了“Demo.class”这个类,因此可以用Class类的getName()方法来获取Demo的类名
Class c = d1.getClass();
System.out.println(c.getName());//结果是Demo
System.out.println(d1.getName());//这样就会出错,因为Demo中没有getName()方法
}
}
class Demo{}
例子:
public class ObjectDemo {
public static void main(String[] args) {
Demo d1 = new Demo(4);
System.out.println(d1.toString());
//结果是:Demo:4
//在实际开发过程中,java很多方法需要重写才能符合我们的使用需求
}
}
class Demo
{
private int num;
Demo(int num)
{
this.num = num;
}
//我们发现toString类返回值没有什么意义,我们将其复写
public String toString()
{
return "Demo:"+num;
}
}
8、Scanner类
键盘输入的几类方法见下面文章:java键盘输入
相应的代码示例如下:
package lkj.demo1;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
public class ScannerTest
{
public static void main(String[] args)throws Exception
{
//键盘输入的几类方法
//Scanner(InputStream source):构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String str1 = sc.next();//输入字符串的方法是next()
System.out.println("输入的字符串是:"+str1);
//使用InputStreamReader类与BufferedReader类
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入字符串:");
String str2 = bufr.readLine();//注意,readLine方法会抛出异常
System.out.println("输入的字符串是:"+str2);
}
}