1、Object
Object 是 Java 类库中的一个特殊类,也是所有类的父类。也就是说,Java 允许把任何类型的对象赋给 Object 类型的变量。当一个类被定义后,如果没有指定继承的父类,那么默认父类就是 Object 类。因此,以下两个类表示的含义是一样的。
public class MyClass{…}
等价于
public class MyClass extends Object {…}
Object类提供无参构造方法 ,之所以提供这样的无参构造,是因为在子类对象实例化时都会默认调用父类中的无参构造方法,这样在定义类时即使没有明确定义父类为Object,读者也不会感觉代码的强制性要求。
Object常用方法
方法 | 说明 |
Object clone() | 创建与该对象的类相同的新对象 |
boolean equals(Object) | 比较两个对象是否相等。默认比较的是地址值。 |
void finalize() | 当垃圾回收器确定不存在对该对象的更多引用时,对象的圾回收器调用该方法 |
Class getClass() | 返回一个对象运行时的实例类(.class文件) |
int hashCode() | 返回该对象的散列码值 |
void notify() | 激活等待在该对象监控器上的一个线程 |
void notifyAll() | 激活等待在该对象的监视器上的全部线程 |
String toString() | 返回该对象的字符串表示,默认返回运行时类名+@+对象的hashCode的16进制数 |
void wait() | 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待 |
常覆写Object类的3个方法:toString(),equals(Object obj),hashCode()
为什么notify(), wait()等函数定义在Object中,而不是Thread中?
Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。
wait()会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!
OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?或者说,wait()等待线程和notify()之间是通过什么关联起来的?答案是:依据“对象的同步锁”。
负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。
总之,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。
注意:
如果两个对象的哈希码值不同,那这两个对象一定不等;
如果两个对象的哈希码值相同,不能确保这两个对象一定相等。
克隆对象对应的类需要实现Cloneable接口,否则会报错:java.lang.CloneNotSupportedException
2、StringBuilder类
线程不安全的可变字符序列
1)构造方法
StringBuilder():以默认容量创建空的StringBuilder对象
StringBuilder(int capacity):以指定容量创建空的StringBuilder对象
StringBuilder(String str):以指定的字符串创建StringBuilder对象
2)成员方法
获取功能
int capacity():获取容量
int length():获取长度
添加功能
append(int value):追加。可以追加多种类型
insert(int offset,String s):在指定的位置插入指定数据
删除功能
deleteCharAt(int index):删除指定索引处的元素
delete(int start,int end):删除[start,start-1]范围内的元素
替换功能
replace(int start,int end,String s):将[start,end-1]范围内的元素替换成指定字符串
反转功能
reverse():元素反转
截取功能
String subString(int start):截取指定位置一直到末尾
String subString(int start,int end):截取[start,end-1]范围
String、StringBuilder和StringBuffer的区别?
String内容不可改变
StringBuilder和StringBuffer内容可变
StringBuilder是线程不安全的,不同步,效率高
StringBuffer是线程安全的,同步,效率低
3、Scanner类
1)构造方法
Scanner(InputStream is)
构造一个文本扫描器,它生成的值是从指定的值输入流扫描的
System.in 是一个标准的输入流,属于InputStream
2)成员方法
boolean hasNext():是否有下一个数,有true,没有false
String next():获取下个数
int nextInt():获取下个int数据
String nextLine():获取一行数据
4、Math类
成员方法
abs(int a):绝对值
ceil(double d):向上取整
floor(double d):向下取整
max(int a,int b):最大值
pow(double a,double b):a的b次幂
random():随机数[0.0,1.0]
round(float f):四舍五入
sqrt(double d):算术平方根
5、Random类
1)构造方法
Random():以当前时间毫秒值作为种子,创建Random对象
Random(long seed):以指定种子创建Random对象
2)成员方法
nextInt():生成1个int类型范围的随机数
nextInt(int n):产生1个[0,n-1]范围内的随机数生成0~n之间的数
①(int)Math.random()*(n+1)
②Random r = new Random();
r.nextInt(m)表示生成[0,m-1]之间的随机数,也就是说random.nextInt(m+1),将生成[0,m]之间的随机整数。
r.nextInt(n+1)
生成n~m之间的随机数
①n+(int)(Math.random()*(m+1-n));
②Random r = new Random();
r.nextInt(m+1-n)+n;
6、Date类
表示特定的瞬间,精确到毫秒值
1)构造方法
Date():以当前时间毫秒值创建Date对象
Date(long time):以指定的毫秒值创建Date对象
2)成员方法
long getTime():获取Date对象的毫秒值
setTime(long time):设置Data对象的毫秒 值
7、DateFormat
它是一个抽象类,用来格式化或者解析日期
格式化:Date————》String
解析:String————》DategetDateInstance(int style,Locale loc):获取日期格式器,该格式器具有给定的语言环境和给定的格式化风格
String format(Date date):格式化
Date parse(String time):解析
8、SimpleDateFormat
它是DateFormat的子类
1)构造方法
SimpleDateFormat():以默认模式创建对象
SimpleDateFormat(String pattern):以指定模式创建对象常用模式
yyyy:年 MM:月 dd:日
HH:时 mm:分 ss:秒2)常成员方法
String format(Date date):格式化
Date parse(String time):解析
9、Calendar类
日历类,用于获取或者操作日历字段(年月日)
该类是一个抽象类,不可以实例化
成员方法
static Calender getInstance():以默认时区和语言创建日历
int get(int field):获取指定字段的日历值
set(int field,int value):给指定的日历字段设置指定的值
set(int year,int month,int date):设置年月日
Date getTime():获取日历对象的日期
setTime(Date d):设置日历对象的日期
add(int field,int amount):对指定的日历字段添加指定的值
10、System类
没有构造方法
成员方法
gc():运行垃圾回收处理机制(系统会在某个不确定的时间调用该方法)
会调用finalize(),进行垃圾回收exit(int status):退出JVM,0表示非异常退出
currentTimeMills():获取当前时间毫秒值
arrayCopy(Object[] srcArr,int srcPos,Object[] desArr,int destPos,int len):数组复制
11、BigInteger类
1)构造方法
BigInteger(String s):通过字符串创建BigInteger对象
2)成员方法
add(BigInteger bi):+
subtract(BigInteger bi):-
multiply(BigInteger bi):*
divide(BigInteger bi):/
12、BigDecimal类
用于解决浮点型运算精度损失的问题
1)构造方法
BigDecimal(String s):通过字符创建BigDecimal对象
2)成员方法
add(BigDecimal bi):+
subtract(BigDecimal bi):-
multiply(BigDecimal bi):*
divide(BigDecimal bi):/
13、String类
永远记住一点:String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象
字符串常量池:
我们知道字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串
Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。
所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。
而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
String a="hello";
String b="hello";
很明显,a、b和字面上的chenssy都是指向JVM字符串常量池中的"chenssy"对象,他们指向同一个对象。而且是在编译器就确定了。
所以a==b 为true
String c=new String("hello");
new关键字一定会产生一个对象chenssy(注意这个chenssy和上面的chenssy不同),同时这个对象是存储在堆中。所以上面应该产生了两个对象:保存在栈中的c和保存堆中chenssy。但是在Java中根本就不存在两个完全一模一样的字符串对象。故堆中的chenssy应该是引用字符串常量池中chenssy。所以c、chenssy、池chenssy的关系应该是:c--->chenssy--->池chenssy。
虽然a、b、c、chenssy是不同的对象,但是从String的内部结构我们是可以理解上面的。String c = new String("chenssy");虽然c的内容是创建在堆中,但是他的内部value还是指向JVM常量池的chenssy的value,它构造chenssy时所用的参数依然是chenssy字符串常量。