java基础类库复习【摘自疯狂java讲义】
今天起,好好学。
运行java程序的参数
main方法的方法签名:
public static void main(String[] args){.....}
解释一下这个签名的意义在哪里?
- public修饰符—java类由JVM调用,为了让JVM可以自由调用这个main()方法,所以java使用public修饰符把这个方法暴露出来。
- static修饰符—静态的,当JVM调用main主方法实收,不会先创建该主类的对象,借用对象去调用这个主方法。java里凡是使用static修饰的方法,被称为静态方法。这类方法,我们直接使用该类去调用这个静态方法。所以JVM直接通过类来调用这个主方法。
- void返回值—无返回值,主方法被JVM调用,返回值返回给JVM没有多大意义,所以使用void,让主方法没有返回值。
- String[] args—至于主方法里的形式参数,谁调用这个主方法,那么他就负责为这个主方法的形参赋值。当JVM调用main方法的时候,因为程序没有给args赋初始值,所以JVM不知道args内容长度,于是JVM将args数组设置成一个长度为0的数组,当我们输出args的时候,会发现他的长度为0。
在学习基础类库时候,强烈建议大家去JAVA官网下载API文档:API文档地址 在官网底下有个 Additional Resources,有不同的API版本,我个人偏向8版本,看大家喜好吧。都很简单的下载,但是很方便我们去学习java的基础。
Scanner类(java.util.Scanner):人机交互作用
- 这个类是我们学习java基础经常使用的一个类,好比如C语言的scanf函数作用,同样是从键盘去吸收录入,但是两个绝对有天大的差距。大家可以现在API文档里面搜索一下这个类。
- 同样的 object类是Java里面所有子类的父类。我不知道大家之前有木有学过继承方面的,如果有相信你很容易理解,如果不懂可以先去了解一下java继承方面的知识。回到正题,Scanner类同样的继承了object类,也从object类那里获得了一些方法,比如从类 java.lang.Object 继承的方法 clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait。这些都是object类的方法,因为Scanner继承了object,所以他可以用object里面的方法。(大家可以在API上了解一下object类的内容)
- Scanner类里面的几个重要的方法:
- hasNextXxx()方法:判断是否还有键盘输入的下一项,Xxx这里表示的是java的基本类型。这个方法返回值是false和true。当然也可以没有Xxx后缀,就带表是否还有下一个字符串。
- nextXxx()方法:获取下一个输入项,这个的返回值就是我们键盘上输入的内容了,有了这个我们可以用输入的内容去做其他的事情。
- 比如下面的代码:
public class ScannerKeyBoardTest
{
public static void main(String[] args)
{
//System.in是标准输入 即就是键盘输入
Scanner sc = new Scanner(System.in)
//增加下一行则系统将回车作为分隔符
//sc.useDelimiter("\n");
//判断是否还有下一项
while(sc.hasNext())
{
//输入输入项
System.out.println("键盘输入的内容是:"+sc.next());
}
}
}
- Scanner还提供了两个方法来逐行读取
- boolean hasNextLine():返回是否还有下一行
- String nextline():返回下一行的字符串
- 另外:Scanner还能读取文件的内容:
即就把标准输入System.in变成文件的名称作为参数。
//Scanner sc = new Scanner(new file(“ScannerTest.java”))//
- 最后还是希望大家多多去看API,了解这个类的其他方法等等,好我们来看下一个基础类。
系统相关类(java.lang.System/Runtime):System类和Runtime类
System类
- 因为java语言的特点之一就是跨平台,不管是windows还是linux系统他都能使用。所以我们在这些系统里敲java时候需要获取系统里的相关属性,而这两个类会帮助我们。还是正常的学习思路,先在API上搜索System这个类。
- 在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
- arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 数组复制方法,静态方法,从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
- currentTimeMillis():静态方法,返回以毫秒为单位的当前时间。返回的时间可以用Date类的对象接收。
- getenv(String name) :获取指定的环境变量值。
- identityHashCode(Object x) :返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()。null 引用的哈希码为 0。
- 这里针对System类的访问系统的方法有一个小的代码 方便大家理解每个方法
package SystemDome;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
/**
* Created by Administrator on 2018/9/21 0021.
* System类方法相关说明
*/
public class SystemTest {
public static void main(String[] args) throws FileNotFoundException {
//获取系统变量
Map<String,String> env = System.getenv(); //返回一个当前系统映射的关系图
for(String name: env.keySet()){
System.out.println(name +"--->"+env.get(name));
}
//获取指定环境变量的值
System.out.println(System.getenv("JAVA_HOME")); //返回指定的环境变量值
//获取所有系统属性
Properties props = System.getProperties(); //确定当前的系统属性。
//将系统属性保存到Props文件中
try {
props.store(new FileOutputStream("props.txt"),"System Properties");
} catch (IOException e) {
e.printStackTrace();
}
//输出特定属性
System.out.println(System.getProperty("os.name"));//获取指定键指示的系统属性。
System.exit(0);
}
}
Runtime类
- runtime代表运行时环境,每个java都有所对应的runtime实例,应用程序通过和运行时环境相连接。但是程序不能创建自己的Runtime实例,需要通过Runtime类里的getRuntime()方法获取。
相关方法 | 说明 |
availableProcessors() | 向 Java 虚拟机返回可用处理器的数目。 |
freeMemory() | 返回 Java 虚拟机中的空闲内存量。 |
totalMemory() | 返回 Java 虚拟机中的内存总量。 |
maxMemory() | 返回 Java 虚拟机试图使用的最大内存量。 |
相关方法API文档查询 | 。。。。。。。。 |
常用类
Object和Objects
- Object类是所有类的父类,它包含了许多实用的方法,java允许把任何对象赋给Object类型的变量。因为所有java类都是object类的子类,所以均可以使用Object类的方法,下来介绍几个方法:
- clone() :创建并返回此对象的一个副本。
- equals(Object obj) :指示其他某个对象是否与此对象“相等”。(通常需要重写这个方法来达到我们想要的相等)。
- finalize() : 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。(系统自动调用 我们不太需要管这个)
- getClass() :返回此 Object 的运行时类
- hashCode() :返回对象的哈希值(一般情况下,我们也要重写这个方法)
- toString():返回该对象的字符串表示。
Objects类 (凡是有s后缀的 基本都是工具类)
- 这个类里面的方法其实和Object差不多,没有太大变化,内容和Object几乎一样,不在详细介绍。
String,StringBuffer,StringBuilder类(java.lang.*)
- 接下来这三个类,是java里经常使用的字符串类。每个类的方法功能都差不多,但是三个各有各的差距。
- String类 是一个不可变的类,当我们创建了String对象后,这个对象的字符序列就被固定,不能改变,知道这个对象被销毁。
- StringBuffer 是一个可变类,这个类提供的许多方法让StringBuffer对象可以随意的增加,设置字符串对象。
- StringBuilder类和StringBuffer类差不多,只不过这个类没有实现线程安全功能,效率略高。通常情况下我们使用第三个类来创建字符串对象。
方法 | 说明 |
charAt(int index) | 返回指定索引处的 char 值。 |
codePointAt(int index) | 返回指定索引处的字符(Unicode 代码点)。 |
codePointBefore(int index) | 返回指定索引之前的字符(Unicode 代码点)。 |
compareTo(String anotherString) | 按字典顺序比较两个字符串。 |
concat(String str) | 将指定字符串连接到此字符串的结尾。 |
contains(CharSequence s) | 当且仅当此字符串包含指定的 char 值序列时,返回 true。 |
contentEquals(CharSequence cs) | 将此字符串与指定的 CharSequence 比较。当且仅当此 String 与指定序列表示相同的 char 值序列时,结果才为 true。 |
contentEquals(StringBuffer sb) | 将此字符串与指定的 StringBuffer 比较。 |
copyValueOf(char[] data) | 返回指定数组中表示该字符序列的 String。 |
copyValueOf(char[] data, int offset, int count) | 返回指定数组中表示该字符序列的 String。 |
endsWith(String suffix) | 测试此字符串是否以指定的后缀结束。 |
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin | 将字符从此字符串复制到目标字符数组。 |
indexOf() | 这个方法也有好多重载方法,作用就是返回索引值(其他的大家在API上查阅吧,我就不一一列举了) |
isEmpty() | 当且仅当 length() 为 0 时返回 true。 |
lastIndexOf() | 同上上。返回最后一次出现的索引值 |
matches(String regex) | 告知此字符串是否匹配给定的正则表达式。 |
valueOf() | 返回 各种参数的字符串表示形式。 |
我介绍的有限 ,更多还是要多看API | … |
Math(java.lang.Math) 数学类,里面包含了我们做数值运算时候的各种函数开方运算。这个类所有的方法都是类方法,直接用Math类名调用即可。具体方法参阅API文档。
ThreadLocalRandom和Random类
- Random类专门生成一个伪随机数。有两个构造器:一个构造器使用默认种子(以当前时间),另一个需要我们传入一个long参数种子。
- ThreadLocalRandom是Random的增强版。在并发访问的环境下,使用ThreadLocalRandom可以减少多线程资源竞争,保证系统具有更好的线程安全性。
- 两个类的用法基本相似,ThreadLocalRandom提供了一个静态方法current()获取TreadLocalRandom对象,然后就可以调用各种nextXxx()来获取伪随机数了。
- 一般情况下,我们为了避免Random产生的数字相同 ,我们使用时间来作为他的参数种子。这样就不会产生相同的随机数了。
Random rand = new Random(System.currentTimeMillis());
- 而在多线程环境下使用的TreadLocalRandom的方式与使用Random相似
ThreadLocalRandom rand = TheadLocalRandom.current();
int val = rand.nextInt(4,20);
int val2 = rand.nextDouble(2.0,10.0);
BigDecimal类(java.math.BigDecimal)
- float 和double 两种基本浮点类型容易引起精度的缺失,例如:
package BigDecimal;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class BigDecimalTest {
public static void main(String[] args) {
System.out.println("0.05 + 0.01 = "+(0.05+0.01));
System.out.println("1.0 - 0.42 = "+(1.0-0.42));
System.out.println("4.015 * 100 = "+(4.015*100));
System.out.println("123.3 / 100 = "+(123.3/100));
}
}
结果:
0.05 + 0.01 = 0.060000000000000005
1.0 - 0.42 = 0.5800000000000001
4.015 * 100 = 401.49999999999994
123.3 / 100 = 1.2329999999999999
上面的程序说明,这些基础类型很容易引起精度确实,尤其是在进行运算的时候。
- 为了精确表示,计算浮点数。java提供了 BigDecimal类 该类提供了大量的构造方法,方便用户使用 数字,数字字符串,数字字符数组来创建BigDecimal对象。
注意:在创建BieDecimal类对象时候,尽量不要使用double做构造器的参数,因为使用这个构造器具有一定的不可预知性。比如,你使用 new BigDecimal(0.1)时,实际上他传入的并不是0.1,而是一个近似于0.1的值。这是因为0.1无法准确的表示为double浮点数。建议优先使用String做传入的参数。
如果必须使用double时,用该这样做:BigDecimal。valueof(double value)静态方法来创建BigDecimal对象。
- 关于BigDecimal类提供的方法:
返回类型 | 方法 | 说明 |
BigDecimal | BigDecimal(BigInteger val / …) | 将各种的基本类型转换为BigDecimal类型 |
BigDecimal | abs() | 返回绝对值 |
BigDecimal | add(BigDecimal augend) | 加法: 返回一个 BigDecimal,其值为 (this + augend) |
int | compareTo(BigDecimal val) | 将此 BigDecimal 与指定的 BigDecimal 比较。比参数大返回1,比参数小 返回-1 和参数相等返回0 |
BigDecimal | divide(BigDecimal divisor) | 除法:返回一个 BigDecimal,其值为 (this / divisor) |
BigDecimal[] | divideAndRemainder(BigDecimal divisor) | 返回由两个元素组成的 BigDecimal 数组 |
基本数据类型 | xxxValue() | 返回xxx的基本类型 比如:doubleValue() |
BigDecimal | max(BigDecimal val)、min(BigDecimal val) | 返回此 BigDecimal 和 val 的最大值或者最小值 |
BigDecimal | movePointLeft(int n) ,movePointRight(int n) | 小数点左移右移 |
BigDecimal | multiply(BigDecimal multiplicand) | 乘法:返回一个 BigDecimal,其值为 (this × multiplicand) |
BigDecimal | pow(int n) | 平方:返回其值为 (this的n平方) 的 BigDecimal |
BigDecimal | remainder(BigDecimal divisor) | 取余:返回其值为 (this % divisor) 的 BigDecimal。 |
BigDecimal | subtract(BigDecimal subtrahend) | 减法: 返回一个 BigDecimal,其值为 (this - subtrahend) |
String | toString() | 返回字符串表示形式 |
更多的方法请参考API | 。。。 | 。。。 |
日期类 Date 和 Calendar类(java.util.Date/Calender)
- Date这个类 就不说了,为什么不说 大家可以百度一下。
- 我们通常同Calender类来进行对时间上的操作。
- Calendar 类:抽象类用于表示日历。他是所有日历类的模板,并提供了一写所有日历通用的方法;但是本身不能实例化,程序只能创建Calendar的子类实例,java提供了一个GregorianCalendar类,表示公历。
- Calendar类是抽象类,不能构造器创建对象。
注意(如何获取Calendar对象):静态方法:getInstance()
Calendar calendar = Calendar.getInstance();
- Calendar 和 Date类是可以自由转换的。例如:
package Calendar;
import java.util.Calendar;
import java.util.Date;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class CalendarTest {
public static void main(String[] args) {
//创建Calendar实例对象
Calendar calendar = Calendar.getInstance();
//从Calendar 对象提取Date
Date date = calendar.getTime();
//通过Date里对象获取对应的Calendar
//因为Calendar类没有构造方法接收Date类 所以需要创建实例
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(date);
System.out.println(calendar.equals(calendar1));
System.out.println(calendar.getTime());
System.out.println(calendar1.getTime());
}
}
结果:
true
Wed Sep 26 11:30:49 GMT+08:00 2018
Wed Sep 26 11:30:49 GMT+08:00 2018
- 关于Calendar类的方法 大家查阅Api文文档吧。接下来说几个需要注意的。
- add和roll方法的区别:
- add方法 (add(int field,int amount)):主要用于改变Calendar特定字段的值。如果需要增加某字段的值,则让amout为正数,反之相反。其次,当修改的字段超过允许的范围时候,会发生进位或者借位。
- 比如 2003-8-23在月数上增加6,会返回 2004-2-23。
- 而当使用roll方法时候,则不会方法进位或者借位的问题。
- 设置Calendar的容错性:setLenient(false)
- 看程序:
package Calendar;
import java.util.Calendar;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class LenientTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
//结果是year字段上加一 mouth字段为1(二月)
calendar.set(Calendar.MONTH,13); // 1
System.out.println(calendar.getTime());
//关闭容错性
//calendar .setLenient(false);
//导致运行时异常
//calendar.set(Calendar.MONTH,13); // 2
//System.out.println(calendar.getTime());
}
}
结果:
Tue Feb 26 11:50:17 GMT+08:00 2019
开启容错性,我们看到程序将月数设成2月,年数加一 ,通过运行。
package Calendar;
import java.util.Calendar;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class LenientTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
//结果是year字段上加一 mouth字段为1(二月)
calendar.set(Calendar.MONTH,13); // 1
System.out.println(calendar.getTime());
//关闭容错性
calendar .setLenient(false);
//导致运行时异常
calendar.set(Calendar.MONTH,13); // 2
System.out.println(calendar.getTime());
}
}
结果:
Exception in thread "main" java.lang.IllegalArgumentException: MONTH
at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2648)
at java.util.Calendar.updateTime(Calendar.java:3393)
at java.util.Calendar.getTimeInMillis(Calendar.java:1782)
at java.util.Calendar.getTime(Calendar.java:1755)
at Calendar.LenientTest.main(LenientTest.java:18)/
开-+错性检查,出现运行时异常,不允许超出范围。
- set()方法延迟修改:set(f,value)方法将日历字段更改为value,此外还设置了一个内部成员变量,以指示f字段已经被修改。尽管是立即更改,但是Calendar代表的时间是不会立即修改,直到下次调用get(),gettime(),gettimeMillis(),add()或者roll()时才会重新计算日历的时间。这就是set()方法的延迟修改机制。
- 好处是多次调用不会触发多次不必要的计算。
package Calendar;
import java.util.Calendar;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class CalendarSetTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2003,7,31); // 2003-8-31
//将月份设置为9月 但是9.31并不存在
//如果立即修改,系统将会自动调到10-1
calendar.set(Calendar.MONTH,8);
//下面输出10-1
System.out.println(calendar.getTime()); // 1
//设置Date为5
calendar.set(Calendar.DATE,5); // 2
System.out.println(calendar.getTime()); // 3
}
}
结果:
Wed Oct 01 14:22:34 GMT+08:00 2003
Sun Oct 05 14:22:34 GMT+08:00 2003
如上面代码所示:起始设置时间 2003 - 8 - 31,然后将月份设置为9月,但是9-31并不存在,系统会知道你修改为9-31,当你要输出的时候,系统会将9-31+1,变为10-1.后面的也将输出 2003-10-5。
当注释掉第一个输出语句时候:
package Calendar;
import java.util.Calendar;
/**
* Created by Administrator on 2018/9/26 0026.
*/
public class CalendarSetTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2003,7,31); // 2003-8-31
//将月份设置为9月 但是9.31并不存在
//如果立即修改,系统将会自动调到10-1
calendar.set(Calendar.MONTH,8);
//下面输出10-1
//System.out.println(calendar.getTime()); // 1
//设置Date为5
calendar.set(Calendar.DATE,5); // 2
System.out.println(calendar.getTime()); // 3
}
}
结果:
Fri Sep 05 14:26:24 GMT+08:00 2003
当注释掉第一个输出语句后,我们将8月增加为9月,系统将记住你设置的2003-9-31,没有第一个输出语句后,系统不会讲9-31修改为10-1.而是在9-31的基础上继续设置date为5,则系统就会设置成2003-9-5日。
上述两个例子说明了set()方法具有程序修改的延迟性。
至此基础类库大致复习到一半,在基础类库(下)里面,将着重复习正则表达式,这是学习java语言的必学重要内容。