从0开始复习java(4)--Class

oracle为java提供了丰富的类库,java8提供了4000多个基础类。java程序员至少要熟悉java中70%的类。

一、交互

使用Scanner获取键盘输入

Scanner是一个基于正则表达式的文本扫描器,它可以从文件、输入流、字符串中解析出基本类型值和字符串值。

Scanner主要提供了两个方法扫描输入:

  • hasNextXxx():是否还有下一个输入项,其中Xxx可以是Int,Long等代表基本数据类型的字符串。
  • nextXxx():获取下一个输入项。
import java.util.Scanner;

public class Test{
    public static void main(String[] args){
        Scanner s = new Scanner(System.in);
        //使用换行符作为分隔符
        s.useDelimiter("\n");
        while (s.hasNext()){
            System.out.println(s.next());
        }
    }
}

默认情况下,Scanner使用空白(空格、tab、回车)作为多个输入项之间的分隔符。

Scanner读取文件输入:

import java.util.Scanner;
import java.io.File;
public class ScannerFileTest{

    public static void main(String[] args) throws Exception{
        Scanner s = new Scanner(new File("ScannerFileTest.java"));
        while(s.hasNextLine()){
            System.out.println(s.nextLine());
        }
        
    }
}

二、系统相关

java提供了SystemRuntime类来与程序的运行平台进行交互。

1、System类

System类代表当前java程序的运行平台,不能创建对象,但是有类变量和类方法可以调用。

提供了代表标准输入、标准输出和错误输出的类变量,并提供一些静态方法访问环境变量、系统属性,还提供了加载文件和动态链接库的方法。

加载文件和动态链接库主要对native方法有用。如java不能访问操作系统底层设备,可以借助c语言完成。实现步骤如下:
1.java程序中声明native修饰的方法,只有方法签名,没有实现,编译该Java文件,生成一个class文件。
2.使用javah编译第一步生成的class文件,产生一个.h文件。
3.写一个cpp文件实现native方法,需要包含第二步的文件(这个文件包含jdk带的jni.h文件)
4.将第三步的cpp文件编译成动态链接库文件。
5.在Java中用System类的loadLibrary()方法或Runtime类的loadLibrary()方法加载第四步产生的动态链接库文件,Java程序中就可以调用这个native方法了。

import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;
import java.util.Properties;

public class SystemTest{
    public static void main(String[] args) throws Exception{
       Map env = System.getenv();
       for(String s : env.keySet()){
           System.out.println(s + "---->" +env.get(s));
       }
       System.out.println(System.getenv("JAVA_HOME"));
       Properties pro = System.getProperties();
       pro.store(new FileOutputStream(new File("properties.txt")), "System Properties");
       System.out.println(System.getProperty("os.name"));
    }
}

System类还提供了通知系统进行垃圾回收的gc()方法,以及通知系统进行资源清理的runFinalization()方法。

System类还有两个获取系统当前时间的方法:currentTimeMillis()nanoTime(),他们返回一个long类型的整数。这个两个方法返回的时间粒度取决于底层操作系统,可能所在的操作系统不支持以毫秒、纳秒作为计时单位。

System类的in、out、err分别代表系统的标准输入(通常是键盘)、标准输出(通常是显示器)和错误输出流,并提供了setIn()setOut()setErr()方法修改。

System类还提供了一个identityHashCode(Object obj)方法,该方法返回指定对象的精确hashCode值,也就是根据对象的地址计算的hashCode。当某个类的hashCode()方法被重写后,该类实例的hashCode()方法不能唯一的标识该对象;但通过该方法依然是根据地址计算的hashCode值。

public class IdentifyHashCode{
    public static void main(String[] args) {
        String s1 = new String("123");
        String s2 = new String("123");
        //String类重写了hashCode方法,根据字符串序列计算hashCode值
        //由于s1和s2序列相同,故其值相同
        System.out.println(s1.hashCode()+"-----"+s2.hashCode());
        System.out.println(System.identityHashCode(s1)+"-----"+System.identityHashCode(s2));
        String s3 = "123";
        String s4 = "123";
        System.out.println(System.identityHashCode(s3)+"-----"+System.identityHashCode(s4));
    }
}

2、Runtime类

Runtime类代表Java程序的运行时环境,每个java程序都有一个与之对应的Runtime实例,应用程序通过该对象与其运行时环境相连。应用程序不能创建自己的Runtime实例,但可以通过getRuntime()方法获取与之相关的对象。

System相似,该类也提供了gc()runFinalization()方法,并提供load(String filename)loadLibrary(String libname)方法加载文件和动态链接库。

Runtime类代表java运行时环境,可以访问jvm的相关信息。如处理器数量,内存信息。

public class RuntimeTest{
    public static void main(String[] args) {
        Runtime rt = Runtime.getRuntime();
        System.out.println(rt.availableProcessors()+""+rt.freeMemory()+rt.totalMemory()+rt.maxMemory());
    }
}
public class RuntimeTest{
    public static void main(String[] args) throws Exception{
        Runtime rt = Runtime.getRuntime();
        rt.exec("notepad.exe");
    }
}

Runtime可以直接单独启动一个进程来运行操作系统的命令。

3、常用类

Object类

所有的java类都是Object类的子类。

object类提供了如下常用方法:

  • boolean equals(Object obj)

判断对象与该对象是否相等。

  • protected void finalize()

当系统中没有引用变量引用到该对象时,垃圾回收期调用该方法清理该对象的资源。

  • Class getClass()

返回该对象的运行时类

  • int hashCode()

返回该对象的hashcode值,默认通过地址计算。

  • String toString()

返回该对象的字符串表示。"运行时类名@十六进制hashCode"

  • wait()
  • notify()
  • notifyAll()

控制线程的暂停和运行。

  • protected clone()

帮助对象实现"自我克隆",即得到对象的副本。

自定义类实现克隆的方法:

  1. 实现Cloneable接口。标记型接口,没有任何方法。
  2. 实现自己的clone()方法。
  3. 实现clone()方法时通过super.clone()调用Object类的clone()方法得到该对象的副本,并返回该副本。
class Address{
    String detail;
    public Address(String detail){
        this.detail = detail;
    }
}

class User implements Cloneable{
    int age;
    Address address;
    public User(int age){
        this.age = age;
    }
    public User clone() throws CloneNotSupportedException{
        return (User)super.clone();
    }
}
public class CloneTest{
    public static void main(String[] args) throws CloneNotSupportedException{
        User u1 = new User(20);
        User u2 = u1.clone();
        //false
        System.out.println(u1==u2);
        //true
        System.out.println(u1.address==u2.address);
    }
}

Object类的clone()方法是浅克隆,只是克隆了对象的所有成员变量值,不会对引用类型变量值所引用的对象进行克隆。

java7新增了一个Objects工具类,这些工具类是"空指针"安全的。如调用一个引用值为null的引用变量的toString()方法,将会引发NullPointerException,但使用Objects.toString(Object o)方法会返回null

import java.util.Objects;

public class ObjectsTest{
    //null
    static ObjectsTest obj;
    public static void main(String[] args) {
        System.out.println(Objects.hashCode(obj));
        System.out.println(Objects.toString(obj));
        System.out.println(Objects.requireNonNull(obj, "obj参数不能是null!"));
    }
}
public Foo(Bar bar){
    //如果bar为null,抛出NullPointerException,不为null时返回参数本身。
    this.bar = Objects.requireNonNull(bar);
}

String、StringBuffer和StringBuilder类

Java提供了StringStringBuffer封装字符串。

String是不可变类。

StringBuffer对象代表一个字符序列可变的字符串。通过StringBuffer提供的append()insert()reverse()setCharAt()setLength()等方法修改字符串的字符序列,然后调用toString()方法转换成字符串对象。

java5新增StringBuilder类,和StringBuffer类基本相似。StringBuffer是线程安全的,StringBuilder性能更高。通常情况下,优先考虑使用StringBuilder

String和StringBuffer、StringBuilder都实现了CharSequence接口,该接口可以认为是字符串的协议接口。

String类的方法:

  • char charAt(int index)
  • int compareTo(String anotherString)

返回第一个不相同字符的字符差,如果s1是s2的子串,s1.compareTo(s2),则返回s1.length()-s2.length()。

  • String concat(String str)
  • boolean contentEquals(StringBuffer sb)
  • static String copyValueOf(char[] data)

String(char[] content)构造器功能相同。

  • Static String copyValuesOf(char[] data, int offset, int count)
  • boolean endsWith(String suffix)
  • boolean equals(Object obj)

如果包含字符串相同,则返回true

  • boolean equalsIgnoreCase(String str)
  • byte[] getBytes()
  • void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
  • int indexOf()
  • int lastIndexOf()
  • int length()
  • String replace(char oldChar, char newChar)
  • boolean startsWith(String prefix)
  • String subString(int beginIndex, int endIndex)
  • char[] toCharArray()
  • String toLowerCase()
  • String toUpperCase()
  • static String valueOf(X x)

StringBufferStringBuilder可以避免String类会产生很多临时变量的问题,这两个类提供了lengthcapacity属性,length包含字符序列的长度。capacity一般比length大。

Math类

ThreadLocalRandom与Random

Random专门生成伪随机数,有一个需要传入long型整数的构造器。

ThreadLocalRandom是Java7新增的类,在并发访问的环境下可以减少多线程资源竞争,保证系统具有更好的线程安全性。与Random类的用法基本相似,提供了静态的current()方法获取该类对象。

BigDecimal类

不建议使用BigDecimal(double val)构造器,建议使用BigDecimal(String val)构造器。提供了各种运算符方法进行基本运算。

不要使用double浮点数作为构造器参数来创建对象,可以使用静态方法BigDecimal.valueOf(double val)

public static BigDecimal valueOf(double val) {
    // Reminder: a zero double returns '0.0', so we cannot fastpath
    // to use the constant ZERO.  This might be important enough to
    // justify a factory approach, a cache, or a few private
    // constants, later.
    return new BigDecimal(Double.toString(val));
}

4、Java8的日期、时间类

Java原本提供有Date类和Calendar类处理日期,但是Date无法国际化,Calendar过于复杂。

Date类

构造器Deprecated的有4个,剩余两个:

  • Date()

生成当前日期时间的Date对象。底层调用System.currentTimeMillis()

  • Date(long date)

根据long整型生成日期对象。参数表示和GMT 1970.01.01 00:00:00到该对象之间的时间差,以毫秒为单位。

除了Deprecated的方法外,还有几个为数不多的方法:

  • boolean after(Date when)
  • boolean before(Date when)
  • long getTime()
  • void setTime(long time)

官方建议尽量少用Date类,需要对日期、时间进行加减运算,或者获取时间的年、月、日、时、分、秒,可以使用Calendar类。

Calendar类

用于弥补Date类的不足。它是一个抽象类,用于表示日历。

Java本身提供了一个GregorianCalendar类,代表了通常所说的公历。

Calendar提供静态方法获取实例。Calendar.getInstance(),可以根据TimeZoneLocale类获取特定的Calendar,不指定则使用默认的。

Calendar和Date可以自由转换:

Calendar c = Calendar.getInstance();
Date d = c.getTime();
Calendar cc = Calendar.getInstance();
cc.setTime(d);

常用方法:

  • void add(int field, int amount)
  • int get(int field)
  • int getActualMaximun(int field)
  • int getActualMinimun(int field)
  • void roll(int field, int amount)
  • void set(int field, int value)
  • void set(int year, int month, int date)
  • void set(int year, int month, int date, int hourOfDay, int minute, int second)

filed是Calendar类的类变量,如Calendar.YEARCalendar.MONTH等。

add和roll的却别

add用于改变Calendar的特点字段的值。有两条规则:

  1. 当被修改字段超过范围时,会发生进位
  2. 如果下一级字段也需要改变,则会修正到变化最小的值。
Calendar c = Calendar.getInstance();
c.set(2003,7,31,0,0,0);
//2003-07-31-->2004-02-29
c.add(MONTH, 6);

roll的规则与add不同,上一级字段不会增大,下一级字段和add相同。

设置Calendar的容错性
Calendar c = Calendar.getInstance();
//关闭容错性
c.setLenient(false);

Calendar有两种解释日历的模式:lenient模式和non-lenient模式。

set方法延迟修改

使用set修改后,calendar所代表的时间不会立即修改,知道下次调用get(),getTime(),getTimeInmillis(),add()或roll()时才会重新计算日历时间。

Java8新增的日期、时间包

java.time包下的类

  • Clock
  • Duration
  • Instant
  • LocalDate
  • LocalTime
  • LocalDateTime
  • MonthDay
  • Year
  • YearMonth
  • ZonedDateTime
  • ZoneId
  • DayOfWeek
  • Month

Java8新增的日期、时间格式器

java.time.format包下提供了一个DateTimeFormatter格式器类。相当于java.text.DateFormatjava.txt.SimpleDateFormat的合体。

你可能感兴趣的:(从0开始复习java(4)--Class)