java基础类库复习【摘自疯狂java讲义】

今天起,好好学。

运行java程序的参数

main方法的方法签名:

public static void main(String[] args){.....}

解释一下这个签名的意义在哪里?

  1. public修饰符—java类由JVM调用,为了让JVM可以自由调用这个main()方法,所以java使用public修饰符把这个方法暴露出来。
  2. static修饰符—静态的,当JVM调用main主方法实收,不会先创建该主类的对象,借用对象去调用这个主方法。java里凡是使用static修饰的方法,被称为静态方法。这类方法,我们直接使用该类去调用这个静态方法。所以JVM直接通过类来调用这个主方法。
  3. void返回值—无返回值,主方法被JVM调用,返回值返回给JVM没有多大意义,所以使用void,让主方法没有返回值。
  4. 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语言的必学重要内容。