1.与用户互动
- 运行Java程序的参数
Java程序的入口
public static void main(String[] args){}
public:为了让JVM自由调用main()方法
static:为了让JVM直接通过类来调用
void:因为主方法是被JVM调用,所以返回给JVM没有意义
String[] args:
方式一(通过代码运行):
public class ArgTest {
public static void main(String[] args) {
System.out.println(args.length);// 将打印0
for(String i : args){// 无输出
System.out.println(i);
}
}
}
方式二(使用命令运行):
java ArgTest Java Spring
// 将打印
// 2
//Java
//Spring
- 使用Scanner获取键盘输入
public class ScannerKeyBoardTest {
public static void main(String[] args) {
// System.in代表键盘输入
Scanner sc = new Scanner(System.in);// 2 3 4
// sc.useDelimiter("\n"); 若使用回车位换行符时,那么Scanner每次读取一行,不以空格作为分隔符读取
while(sc.hasNext()){
System.out.println("键盘输入的内容是"+sc.next());
// 键盘输入的内容是2
// 键盘输入的内容是3
// 键盘输入的内容是4
}
}
}
Scanner提供了两个简单的方法来逐行读取
boolean hasNextLine()
String nextLine()
Scanner不仅可以获取字符串输入项,也可以获取
2.系统相关
Java提供了System类和Runtime类来与程序的运行平台进行交互
- System类
System类代表当前Java程序的运行平台,程序不能创建System类的对象(构造方法为private),System类提供了一些变量和方法,
允许直接通过System类来调用这些类变量和类方法。
System类提供了:
1. 标准输入、标准输出、错误输出
2. 静态方法访问环境变量、系统属性
3. 加载文件和动态链接库的方法
(System类或Runtime类的LoadLibrary..()方法)
- 获取系统当前时间 currentTimeMillis()和nanoTime() 返回与UTC1970年1月1日 毫秒差 纳秒差
public class SystemTest {
public static void main(String[] args) throws Exception {
// 获取系统所有的环境变量
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.txt文件中
props.store(new FileOutputStream("props.txt"),"System Properties");
// 输出特定的系统属性
System.out.println(System.getProperty("os.name"));
}
}
System类提供了identityHashCode(Object x)方法,返回指定对象的精确hashCode值,也就是根据对象的地址得到的hashCode值
public class IdentityHashCodeTest {
public static void main(String[] args) {
String a = new String("a");
String b = new String("a");
System.out.println(a.hashCode()==b.hashCode());// true
System.out.println(System.identityHashCode(a)==System.identityHashCode(b));// false
}
}
- Runtime类
Runtime类代表Java程序的运行环境,每个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与其运行时环境相连。
应用程序不能创建自己的Runtime实例,但可以通过getRuntime()方法获取与之关联的Runtime对象。
Runtime可以访问JVM的相关信息,如处理器数量、内存信息等。
public class RuntimeTest {
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
System.out.println("处理器数量"+rt.availableProcessors());
System.out.println("空闲内存数"+rt.freeMemory());
System.out.println("总内存数"+rt.totalMemory());
System.out.println("可用最大内存数"+rt.maxMemory());
}
}
Runtime可以单独启动一个进程来运行操作系统的命令
public class ExecTest {
public static void main(String[] args) throws Exception{
Runtime rt = Runtime.getRuntime();
// 运行记事本程序
rt.exec("notepad.exe");
}
}
3.常用类
- Object类
Object类的方法
1. equals:比较的是对象的地址是否相等
2. finalize:垃圾回收器调用此方法回收资源
3. getClass:返回对象运行时类
4. hashCode:根据对象地址计算出(即精确System.identityHashCode(Object x))
5. toString:返回“运行时类名@十六进制hashCode值”
6. wait(),notify(),notifyAll()用来控制线程
7. clone:得到当前对象的副本,而且二者完全隔离
// 1.实现Cloneable接口
// 2.自定义类实现自己的clone()方法
//实现clone方法时使用super.clone();
class Address{
String detail;
public Address(String detail){
this.detail=detail;
}
}
public class CloneTest implements Cloneable {
int age;
Address a;
public CloneTest(Address a,int age){
this.a=a;
this.age=age;
}
public CloneTest clone() throws CloneNotSupportedException {
return (CloneTest)super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Address a = new Address("中山路18号");
CloneTest cloneTest1 = new CloneTest(a,18);
CloneTest cloneTest2 = cloneTest1.clone();
System.out.println(cloneTest1==cloneTest2);// false 代表克隆出的对象 与之前的对象 具有不同的地址
System.out.println(cloneTest1.a==cloneTest2.a);// true 代表克隆后,引用类型成员变量的地址是相同的
System.out.println(cloneTest1.age==cloneTest2.age);// true
}
}
注意:Object类提供的clone机制只对对象里各实例变量进行“简单复制”,但它只是一种“浅克隆”
–它不会对引用类型的成员变量值所引用的对象进行克隆。
–如果开发者需要对对象进行“深克隆”,则需要开发者自己进行“递归”深克隆,保证所有引用类型的成员变量值所引用的对象都被复制了。
浅克隆
package chapter7.shallowClone;
/**
* Created by liudy on 16/10/26.
* 继承自java.lang.Object类的clone()方法是浅复制。
* 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不
* 复制它所引用的对象。
*/
class Professor {
String name;
int age;
Professor(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Student implements Cloneable {
String name;// 常量对象。
int age;
Professor p;// 学生1和学生2的引用值都是一样的。
Student(String name, int age, Professor p) {
this.name = name;
this.age = age;
this.p = p;
}
public Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Professor p = new Professor("wangwu", 50);
Student s1 = new Student("zhangsan", 18, p);
Student s2 = s1.clone();
s2.p.name = "lisi";
s2.p.age = 30;
// s2=null; // s1的studet引用不变
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);//学生1的教授成为lisi,age为30。
}
}
深克隆
package chapter7.deepClone;
/**
* Created by liudy on 16/10/26.
* 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原
* 有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
*/
class Professor implements Cloneable {
String name;
int age;
Professor(String name, int age) {
this.name = name;
this.age = age;
}
public Professor clone() throws CloneNotSupportedException {
return (Professor) super.clone();
}
}
class Student implements Cloneable {
String name;
int age;
Professor p;
Student(String name, int age, Professor p) {
this.name = name;
this.age = age;
this.p = p;
}
public Student clone() throws CloneNotSupportedException {
Student o=null;
o=(Student) super.clone();
o.p=p.clone();
return o;
// 针对每一个引用再克隆一遍
}
public static void main(String[] args) throws CloneNotSupportedException {
Professor p = new Professor("wangwu", 50);
Student s1 = new Student("zhangsan", 18, p);
Student s2 = s1.clone();
s2.p.name = "lisi";
s2.p.age = 30;
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);//学生1的教授不 改变。
}
}
利用串行化进行深克隆(待补充)
- java7新增的Objects类
Objects类是工具类,它提供了一些方法来操作对象,这些工具方法是“空指针”安全的。
package chapter7.three;
import java.util.Objects;
/**
* Created by dongyu.liu on 2016/10/25.
*/
public class ObjectsTest {
static Object obj;
public ObjectsTest(Object obj){
// 该方法主要用来对方法形参进行输入校验
this.obj = Objects.requireNonNull(obj,"参数不能为null");
}
public static void main(String[] args) {
System.out.println(Objects.hashCode(obj));// 0
System.out.println(Objects.toString(obj));// null
System.out.println(null==null);// null
// 该方法主要用来对方法形参进行输入校验
System.out.println(Objects.requireNonNull(obj,"参数不能为null!"));
}
}
- String、StringBuffer和StringBuilder类
这三个类都实现了CharSequence接口
String:不可变类,对象一旦被创建则不可被改变,直至销毁
StringBuffer: 对象代表一个字符序列可变的字符串,可通过调用toString()方法将其转换为一个String对象
StringBuilder:也代表字符串对象,与StringBuffer类似,但是没有实现线程安全功能,所以性能略高。因此通常考虑使用StringBuilder类
String类提供了大量的构造器来创建String对象:
package chapter7.three;
/**
* Created by dongyu.liu on 2016/10/25.
*/
public class StringTest {
public static void main(String[] args) {
System.out.println("***************String类的构造器*******************");
// new String()
String d = new String();
System.out.println("d:" + d);// d是包含0个字符串序列的String对象
// 通过StringBuffer创建String对象
StringBuffer buffer = new StringBuffer("abc");
String a = new String(buffer);
System.out.println("a:" + a);
// 通过StringBuilder创建String对象
StringBuilder builder = new StringBuilder("def");
String b = new String(builder);
System.out.println("b:" + b);
// 通过original创建String
String c = new String("aaa");
System.out.println("c:" + c);
// byte[]
byte[] byteArr = new byte[]{49, 50, 51};
String e = new String(byteArr);
System.out.println("e:" + e);// 123
// String(byte[] bytes,Charset charset)
byte[] byteArr2 = new byte[]{49, 50, 51};
String f = new String(byteArr, Charset.defaultCharset()); //Charset.defaultCharset().name()- utf-8
System.out.println("f:" + f);// 123
// String(byte[] bytes,int offset,int length)
byte[] ba1 = {49, 50, 51};
String h = new String(ba1, 0, ba1.length);
System.out.println("h:" + h);
// String(byte[] bytes,int offset,int length,String charsetName)
byte[] ba = {49, 50, 51};
String g = new String(ba, 0, ba.length, "utf-8");
System.out.println("g:" + g);
// String(byte[] bytes,String charsetName)
byte[] ba2 = {49, 50, 51};
String i = new String(ba2, "utf-8");
System.out.println("i:" + i);
// String(char[] value,int offset,int count)
byte[] ba3 = {49, 50, 51};
String j = new String(ba3, 0, 2);
System.out.println("j:" + j);
}
}
String类提供了大量的方法来操作字符串对象:
System.out.println("***************String类提供的大量方法*******************");
// 待整理
// System.out.println("unicode码为" + s7.codePointCount(0,2));// 2
// offsetByCodePoints
// contentEquals
// subSequence
// matches
// public boolean contains(CharSequence s)
// public String replaceFirst(String regex, String replacement)
// replaceAll
// public String replace(CharSequence target,CharSequence replacement)
// public String[] split(String regex,int limit)
// public String[] split(String regex)
// public String toLowerCase(Locale locale)
// public String toUpperCase(Locale locale)
// public static String format(String format,Object... args)
// public static String format(Locale l,String format,Object... args)
// copyValueOf(char[] data)和valueOf(char[] data)目前没发现有什么区别。。。
//intern()
//charAt()
String s = new String("fkit.org");
System.out.println("s.charAt(5)" + s.charAt(5)); // o
// int compareTo(String anotherString)
String s1 = new String("abcdefghijklmn");
String s2 = new String("abcdefghij");
String s3 = new String("abcdefghijalmn");
String s4 = new String("abcdefghijklmn");
System.out.println(s1.compareTo(s4));// 相等 输出0
System.out.println(s1.compareTo(s3));// 返回 'k'-'a'的差
System.out.println(s1.compareTo(s2));// 返回长度差
// String concat(String stc) 连接两个字符串
String c1 = "aaa";
String c2 = "bbb";
String c3 = c1.concat(c2);
System.out.println("c3:" + c3);
// String与StringBuffer比较 序列相同返回true boolean contentEquals(StringBuffer sb)
boolean strBoolean = new String("123").contentEquals(new StringBuffer("123"));
System.out.println(strBoolean);
// int
String s5 = "123";
System.out.println(s5.length());
// boolean
String s6 = new String();
String s7 = new String("123");
System.out.println(s6.isEmpty());// true
System.out.println(s7.isEmpty());// false
// int
System.out.println("unicode码为" + s7.codePointAt(0));// 49
// int
System.out.println("unicode码为" + s7.codePointBefore(1));// 49
// void 拷贝到char[]
String s8 = new String("12345678");
char[] charArr = new char[8];
s8.getChars(0, 8, charArr, 0);
System.out.println(Arrays.toString(charArr));
// byte[]
byte[] ba4 = new byte[8];
ba4 = s8.getBytes();
System.out.println(Arrays.toString(ba4));
//
ba4 = s8.getBytes(Charset.defaultCharset());
//
ba4 = s8.getBytes(Charset.defaultCharset().name());
// boolean
String s9 = "abc";
String s10 = "ABC";
System.out.println(s9.equalsIgnoreCase(s10));
// boolean
System.out.println(s9.compareToIgnoreCase(s10));
//boolean
String s11 = "123GHI";
String s12 = "45643GHi";
System.out.println("两个字符串子串比较" + s11.regionMatches(3, s12, 5, 3));// false
//
System.out.println("两个字符串子串比较,忽略大小写" + s11.regionMatches(true, 3, s12, 5, 3));// true
// boolean
System.out.println("是否以4开头" + s12.startsWith("4"));
// boolean
System.out.println("索引为5是否是G开头" + s12.startsWith("G", 5));
// boolean
System.out.println(s12.endsWith("i"));
// int
System.out.println(s11.hashCode());// 1450594326
String s13 = "123GHI";
System.out.println(s13.hashCode() == s11.hashCode());// true
// int
String s14 = "123GHI12378781234";
System.out.println(s14.indexOf(49));// 49对应的字符是1
// int
System.out.println("从索引3开始" + s14.indexOf(49, 3)); // 6
// int
System.out.println(s14.lastIndexOf(49)); // 13
// int
System.out.println(s14.lastIndexOf(49, 7)); // 6
// int
System.out.println(s14.indexOf("123"));// 0
System.out.println(s14.indexOf("1230"));// -1
// int
System.out.println(s14.indexOf("123", 4)); //6
// int
System.out.println(s14.lastIndexOf("123"));// 13
//int
System.out.println("最后一次出现的索引" + s14.lastIndexOf("123", 7));// 6
// String
System.out.println("substring:" + s14.substring(6));
// String
// String s14 = "123GHI12378781234";
System.out.println("0-4substring:" + s14.substring(0, 4));
// string
System.out.println("替换后为" + s14.replace('1', '8'));
// string
String s15 = " abd DfsDIIJa ";
System.out.println(s15.toLowerCase());// abddfsdiija
System.out.println(s15.toUpperCase());// ABDDFSDIIJA
// string
System.out.println(s15.trim());// 忽略前导空白和尾部空白
// string
System.out.println(s15.toString());
// char[] 把字符串转成字符数组
char[] charArr2 = new char[20];
charArr2 = s15.toCharArray();
System.out.println(Arrays.toString(charArr2));
// string
Object object = new Student("zhangsan",18);
System.out.println(String.valueOf((byte)1));
System.out.println(String.valueOf((short)1));
System.out.println(String.valueOf((char)1));
System.out.println(String.valueOf((int)1));
System.out.println(String.valueOf((long)1));
System.out.println(String.valueOf((float)3.4));
System.out.println(String.valueOf(3.4));
System.out.println(String.valueOf(true));
System.out.println(String.valueOf(object));// chapter7.Student@61bbe9ba
// 把字符数组转成字符串
System.out.println(String.valueOf(s15.toCharArray()));
System.out.println(String.valueOf(s15.toCharArray(),0,4));
System.out.println(String.copyValueOf(s15.toCharArray()));
System.out.println(String.copyValueOf(s15.toCharArray(),0,4));
StringBuffer和StringBuilder有两个属性,length和capacity。二者的length可改变,可通过length()和setLength(int len)来访问和修改。
capacity表示容量,程序通常无须关心。
package chapter7.three;
/**
* Created by dongyu.liu on 2016/10/26.
*/
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("java");// java
sb.insert(0,"hello ");// hello java
System.out.println(sb);
sb.replace(5, 7, ",");// hello,ava
System.out.println(sb);
sb.delete(5,6);// helloava
System.out.println(sb);
sb.reverse();// avaolleh
System.out.println(sb);
System.out.println(sb.length());// 8
System.out.println(sb.capacity());// 16
sb.setLength(5);// avaol
System.out.println(sb);
}
}
- Math类
Math类不能创建实例(构造器为private),所有方法都是类方法,还提供了两个类变量PI和E(public static final修饰)。
下面基本覆盖Math类所有的数学计算功能。
package chapter7.three;
/**
* Created by dongyu.liu on 2016/10/26.
*/
public class MathTest {
public static void main(String[] args) {
//---------------下面是三角运算----------------------
System.out.println(Math.PI);
System.out.println(Math.toDegrees(1.57));// 弧度转角度
System.out.println(Math.toRadians(90));// 角度转弧度
System.out.println(Math.sin(1.57));// 计算正弦
System.out.println(Math.atan2(0.1,0.2));// 将矩形坐标转换为极坐标
//---------------下面是取整运算----------------------
System.out.println(Math.floor(1.2));// 1 小于目标最大整数
System.out.println(Math.ceil(1.2));// 2 大于目标最小整数
System.out.println(Math.round(2.3));// 2 四舍五入
//---------------下面是乘方、开方、指数运算----------------------
System.out.println(Math.pow(3,2));// 乘方
System.out.println(Math.log(12));// 自然对数
System.out.println(Math.log10(9));// 底数为10的对数
System.out.println(Math.log1p(9));// 参数与1之和的自然对数
//---------------下面是符号相关运算----------------------
System.out.println(Math.abs(-4.5));// 绝对值 4.5
System.out.println(Math.copySign(1.2,-1.0));// 符号赋值,返回带有第二个浮点数符号的第一个浮点数值 -1.2
System.out.println(Math.signum(2.3));// 符号函数 1.0
//---------------下面是大小相关运算----------------------
System.out.println(Math.max(2.3,4.4));// 4.4
System.out.println(Math.min(2.3,4.4));// 2.3
System.out.println(Math.nextAfter(1.2,1.0));// 1.1999999999999997 返回第一个参数和第二个参数之间与第一个参数相邻的浮点数
System.out.println(Math.nextUp(1.2));// 返回比目标数略大的浮点数 2000000000000002
System.out.println(Math.random());// 返回一个伪随机数,该值大于0.0且小于1.0
}
}
- Java7的ThreadLocalRandom与Random
Random类专门用于生成一个伪随机数,它有两个构造器,一个使用默认种子(当前时间),一个需要程序员显示传入long型整数种子。
ThreadLocalRandom是Random类的增强版,在并发访问的情况下,可以减少多线程资源竞争,最终保证系统具有更好的线程安全性.
ThreadLocalRandom,通过静态的current()来获取对象,通过调用nextXxx()方法来获取伪随机数。
二者都比Math.random()方法提供了更多方式生成伪随机数。(可指定随机数的类型和范围)
package chapter7.three;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* Created by dongyu.liu on 2016/10/26.
*/
public class RandomTest {
public static void main(String[] args) {
Random rand = new Random();
System.out.println(rand.nextBoolean());
byte[] buffer = new byte[16];
rand.nextBytes(buffer);
System.out.println(Arrays.toString(buffer));
// 生成0.0-1.0之间的伪随机double数
System.out.println();
// 生成0.0-1.0之间的伪随机float数
System.out.println(rand.nextFloat());
// 生成平均值是0.0,标准差是1.0的伪高斯数
System.out.println(rand.nextGaussian());
// 生成一个处于int取值范围内的整数
System.out.println(rand.nextInt());
// 生成0-26的伪随机整数
System.out.println(rand.nextInt(26));
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
}
}
Random使用一个48位的种子,如果这个类的两个实例是同一个种子创建的,并对它们以同样的顺序调用方法,则它们会产生相同的数字序列。
所以Random产生的数字并不是真正随机的,而是一种伪随机。
package chapter7.three;
import java.util.Random;
/**
* Created by dongyu.liu on 2016/10/26.
*/
public class SeedTest {
public static void main(String[] args) {
Random rd1 = new Random(50);
Random rd2 = new Random(50);
System.out.println(rd1.nextInt()==rd2.nextInt());// true
System.out.println(rd1.nextBoolean()==rd2.nextBoolean());// true
}
}
为了避免产生相同的数字序列,通常推荐使用当前时间作为种子
Random rand = new Random(System.currentTimeMillis());
多线程环境下使用ThreadLocalRandom的方式与Random基本类似
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
// 生成一个4-20间的伪随机整数
System.out.println(threadLocalRandom.nextInt(4,20));
// 2.0-10.0之间的伪随机浮点数
System.out.println(threadLocalRandom.nextDouble(1.0,2.0));
- BigDecimal类
float、double容易引起精度丢失,例如0.05+0.01=0.0600000000000005
所以为了精确表示浮点数,java提供了BigDecimal类,该类提供了大量构造器,包括把所有基本数值类型转换成一个BigDecimal对象,
也包括利用数字字符串、数字字符数组来创建BigDecimal对象。
构造器BigDecimal(double val)的结果不可预知,例如传入0.1,它的实际值是近似0.1的数。
构造器BigDecimal(String val)的结果可与之,传入0.1,正好等于预期的0.1
如果必须使用double作为参数,那么应该通过构造器BigDecimal.valueOf(double val)来创建对象
BigDecimal类提供了add()、substract()、multiply()、divide()、pow()对精确浮点数进行常规运算
package chapter7.three;
import java.math.BigDecimal;
/**
* Created by dongyu.liu on 2016/10/27.
*/
public class BigDecimalTest {
public static void main(String[] args) {
BigDecimal f1 = new BigDecimal("0.05");
BigDecimal f2 = BigDecimal.valueOf(0.01);
BigDecimal f3 = new BigDecimal(0.05);
System.out.println(f1.add(f2));// 0.06
System.out.println(f1.subtract(f2));// 0.04
System.out.println(f1.multiply(f2));// 0.0005
System.out.println(f1.divide(f2));// 5
System.out.println(f3.add(f2));// 不精确
}
}
BigDecimal工具类
package chapter7.three;
import java.math.BigDecimal;
/**
* Created by dongyu.liu on 2016/10/27.
*/
public class Arith {
private static final int DEF_DIV_SCALE = 10;
// BigDecimal的工具类
private Arith() {
}
// add
public static double add(double a, double b) {
BigDecimal b1 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
return b1.add(b2).doubleValue();
}
// sub
public static double sub(double a, double b) {
BigDecimal b1 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
return b1.subtract(b2).doubleValue();
}
// mul
public static double mul(double a, double b) {
BigDecimal b1 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
return b1.multiply(b2).doubleValue();
}
// divide 精确到小数点后10位的数字四舍五入
public static double div(double a, double b) {
BigDecimal b1 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
return b1.divide(b2,DEF_DIV_SCALE,BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args) {
//
}
}