Object类
Object类是所有类、数组、枚举类的父类,即Java允许把任何类型的对象赋给Object类型的变量。当定义一个类没有使用extends关键字为它显示指定父类,则该类默认继承Object父类。
//常用方法:
boolean equals(Object obj)
protected void finalize()
Class<?>getClass()
int hashCode()
String toString()
Java还提供了一个protected修饰的clone()方法,该方法用于帮助其他对象来实现“自我克隆”,即得到一个当前对象的副本,而且二者完全隔离。
- 自定义类实现“克隆”步骤如下:
- 自定义类实现Cloneable接口。
- 自定义类实现自己的clone()方法。
- 实现clone()方法时通过super.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;
address = new Address("bala");
}
//通过调用super.clone()来实现clone()方法
public User clone() throws CloneNotSupportedException {
return (User)super.clone();
}
}
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User(29);
User u2 = u1.clone();
System.out.println(u1 == u2); //false
System.out.println(u1.address == u2.address); //true
}
}
String、StringBuffer和StringBuilder类
- String类是不可变类,一旦一个String对象被创建以后,包含在这个对象里的字符串序列是不可改变的,直至这个对象被销毁。
- StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
- StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。但是StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。因此在通常情况下,需要创建一个内容可变的字符串对象,优先考虑使用StringBuilder类。
String、StringBuffer、StringBuilder都实现了CharSequence接口,因此CharSequence可认为是一个字符串的协议接口。
String():创建一个包含0个字符串序列的String对象(并非null)
String(byte[] bytes, Charset charset):使用指定的字符集将指定的byte[]数组解码成一个新的String对象
String(byte[] bytes, int offset, int length)
String(byte[] bytes, int offset, int length, String charsetName)
String(char[] value, int offset, int count)
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder)
char charAt(int index):获取字符串中指定位置的字符
int compareTo(String anotherString)
String concat(String str)
boolean contentEquals(StringBuffer sb)
static String copyValueOf(char[] data)
static String copyValueOf(char[] data, int offset, int count)
boolean endsWith(String suffix):返回该String对象是否以suffix结尾
boolean equals(Object anObject)
boolean equalsIgnoreCase(String str):同上,忽略大小写
byte[] getBytes()
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
int indexOf(int ch)
int indexOf(int ch, int fromIndex)
int indexOf(String str)
int indexOf(String str, int fromIndex)
int lastIndexOf(int ch)
int lastIndexOf(int ch, int fromIndex)
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex)
int length()
String replace(char oldChar, char newChar)
boolean startsWith(String prefix)
boolean startsWith(String prefix, int toffset)
String substring(int beginIndex)
String substring(int beginIndex, int endIndex)
char[] toCharArray():将String对象转换成char数组
String toLowerCase()
String toUpperCase()
static String valueOf(X x)
Math类
Java提供了Math工具类来完成一些复杂的运算,它的构造器被定义为private的,因此无法创建Math类的对象;Math类中的所有方法都是类方法,可以直接通过类名来调用它们。除了大量的静态方法之外,还提供了两个类变量:PI和E。
public class MathTest {
public static void main(String[] args) {
/*--------------------三角运算--------------------*/
System.out.println("Math.toDegrees(1.57):" + Math.toDegrees(1.57));
//弧度转换成角度
System.out.println("Math.toRadians(90):" + Math.toRadians(90));
//角度转换成弧度
System.out.println("Math.acos(1.2):" + Math.acos(1.2));
System.out.println("Math.asin(0.8):" + Math.asin(0.8));
System.out.println("Math.atan(2.3):" + Math.atan(2.3));
//计算反余弦、反正弦、反正切
System.out.println("Math.cos(1.57):" + Math.cos(1.57));
System.out.println("Math.sin(1.57):" + Math.sin(1.57));
System.out.println("Math.tan(0.8):" + Math.tan(0.8));
//计算余弦、正弦、正切
System.out.println("Math.cosh(1.2):" + Math.cosh(1.2));
System.out.println("Math.sinh(1.2):" + Math.sinh(1.2));
System.out.println("Math.tanh(2.1):" + Math.tanh(2.1));
//计算双曲余弦、双曲正弦、双曲正切
System.out.println("Math.atan2(0.1,0.2):" + Math.atan2(0.1,0.2));
//将矩形坐标(x,y)转换成极坐标(r,thet)
/*--------------------取整运算--------------------*/
System.out.println("Math.floor(-1.2):" + Math.floor(-1.2));
//取整,返回小于目标数的最大整数
System.out.println("Math.ceil(1.2):" + Math.ceil(1.2));
//取整,返回大于目标数的最小整数
System.out.println("Math.round(2.3):" + Math.round(2.3));
//四舍五入取整
/*----------------乘方、开方、指数运算---------------*/
System.out.println("Math.sqrt(2.3):" + Math.sqrt(2.3));
//计算平方根
System.out.println("Math.cbrt(9):" + Math.cbrt(9));
//计算立方根
System.out.println("Math.exp(2):" + Math.exp(2));
//返回e的n次幂
System.out.println("Math.hypot(4,4):" + Math.hypot(4, 4));
//返回sqrt(x方+y方)
System.out.println("Math.IEEEremainder(5,2):" + Math.IEEEremainder(5, 2));
//按照IEEE754标准的规定,对两个参数进行余数运算
System.out.println("Math.pow(3,2):" + Math.pow(3,2));
//计算乘方
System.out.println("Math.log(12):" + Math.log(12));
//计算自然对数
System.out.println("Math.1og10(9):" + Math.log10(9));
//计算底数为10的对数
System.out.println("Math.log1p(9):" + Math.log1p(9));
//计算参数与1之和的自然对数
/*------------------符号相关的运算-----------------*/
System.out.println("Math.abs(-4.5):" + Math.abs(-4.5));
//计算绝对值
System.out.println("Math.copySign(1.2, -1.0):" + Math.copySign(1.2, -1.0));
//符号赋值,返回带有第二个浮点数符号的第一个浮点参数
System.out.println("Math.signum(2.3):" + Math.signum(2.3));
//符号函数,如果参数为0返回0,参数大于0返回1.0,参数小于0返回-1.0
/*------------------大小相关的运算-----------------*/
System.out.println("Math.max(2.3,4.5):" + Math.max(2.3,4.5));
//找出最大值
System.out.println("Math.min(1.2,3.4):" + Math.min(1.2,3.4));
//找出最小值
System.out.println("Math.nextAfter(1.2,1.0):" + Math.nextAfter(1.2,1.0));
//返回第一个参数和第二个参数之间与第一个参数相邻的浮点数
System.out.println("Math.nextUp(1.2):" + Math.nextUp(1.2));
//返回比目标数略大的浮点数
System.out.println("Math.random():" + Math.random());
//返回一个伪随机数,该值大于等于0.0且小于1.0
}
}
ThreadLocalRandom与Random类
Random类专门用于生成一个伪随机数,它有两个构造器:一个构造器使用默认的种子(以当前时间作为种子),另一个构造器需要显式传入一个long型整数的种子。
ThreadLocalRandom类是Random的增强版。使用它来代替Random可以减少多线程资源竞争,保证系统具有更好的线程安全性。
import java.util.Arrays;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
Random rand = new Random();
System.out.println("rand.nextBoolean():" + rand.nextBoolean());
byte[] buffer = new byte[16];
rand.nextBytes(buffer);
System.out.println(Arrays.toString(buffer));
//生成0.0~1.0之间的伪随机double数
System.out.println("rand.nextDouble():" + rand.nextDouble());
//生成0.0~1.0之间的伪随机float数
System.out.println("rand.nextFloat():" + rand.nextFloat());
//生成平均值是0.0,标准差是1.0的伪高斯数
System.out.println("rand.nextGaussian():" + rand.nextGaussian());
System.out.println("rand.nextInt():" + rand.nextInt());
System.out.println("rand.nextInt(26):" + rand.nextInt(26));
//生成一个处于long整数取值范围的伪随机数
System.out.println("rand.nextLong():" + rand.nextLong());
}
}
要注意的是,如果两个Random对象的种子相同,而且方法的调用顺序也相同,它们最终就会产生相同的数字序列,也就是一种伪随机。
所以通常使用当前时间作为Random对象的种子:
Random rand = new Random(System.currentTimeMillis());
BigDecimal类
float和double两种基本类型的浮点数容易引起精度丢失,为了能精确表示、计算浮点数,BigDecimal类提供了大量的构造器用于创建其对象。
使用BigDecimal构造器有一定的不可预知性。用new BigDecimal(0.1)来创建一个对象时,它的值并不是0.1,而是一个近似0.1的数。这是因为0.1无法准确地表现为double浮点数,所以传入的值不会正好等于0.1。
import java.math.BigDecimal;
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("使用String作为BigDecimal构造器参数:");
System.out.println("0.05 + 0.01 = " + f1.add(f2));
System.out.println("0.05 - 0.01 = " + f1.subtract(f2));
System.out.println("0.05 * 0.01 = " + f1.multiply(f2));
System.out.println("0.05 / 0.01 = " + f1.divide(f2));
System.out.println("使用double作为BigDecimal构造器参数:");
System.out.println("0.05 + 0.01 = " + f3.add(f2));
System.out.println("0.05 - 0.01 = " + f3.subtract(f2));
System.out.println("0.05 * 0.01 = " + f3.multiply(f2));
System.out.println("0.05 / 0.01 = " + f3.divide(f2));
}
}
BigDecimal进行算术运算,创建BigDecimal对象时,要使用String对象作为构造器参数,而不是直接使用double数字。
以BigDecimal为基础定义一个Arith工具类,来进行double浮点数加减乘除运算,再将结果转换为double型变量:
import java.math.BigDecimal;
public class Arith {
private static final int DEF_DIV_SCALE = 10;
private Arith() {}
public static double add(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}
public static double sub(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.subtract(b2).doubleValue();
}
public static double mul(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).doubleValue();
}
public static double div(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args) {
System.out.println("0.05 + 0.01 = " + Arith.add(0.05, 0.01));
System.out.println("1.0 - 0.42 = " + Arith.sub(0.05, 0.01));
System.out.println("4.015 * 100 = " + Arith.mul(4.015, 100));
System.out.println("123.3 / 100 = " + Arith.div(123.3, 100));
}
}