1.registerNatives()
用于声明注册原生方法
private static native void registerNatives();
static {
registerNatives();
}
所有的Object方法都会有一个 native 声明,如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现,如:
public final native Class<?> getClass();
2.getClass()
public final native Class<?> getClass();
返回:路径.类名
如:com.example.entity.UserInfo
在反射编程中经常用到,<?>表示可以是任意类型。如果对象被强转,返回的依然是原对象的class,比如(Object)UserInfo,返回com.example.entity.UserInfo,而不是java.lang.Object。
3.hashCode()
public native int hashCode();
每个对象都有自己的哈希值,同一个对象当对象的属性不一致时,返回的哈希值也是不一样的。
4.equals()
public boolean equals(Object obj) {
return (this == obj);
}
注意区分==和equals,由equals的源码可以看出这里定义的equals与==是等效的(Object类中的equals没什么区别),不同的原因就在于有些类(像String、Integer等类)对equals进行了重写,但是没有对equals进行重写的类(比如我们自己写的类)就只能从Object类中继承equals方法,其equals方法与==就也是等效的,除非我们在此类中重写equals。
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
if (aa == bb) // true
System.out.println("aa==bb");
if (a == b) // false,非同一对象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 == 42.0) { // true
System.out.println("true");
}
}
String.java 中的equals就做了重写
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
//== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地
//址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
}
if (anObject instanceof String) {//是否时String 类型 如果不是直接返回false
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {//length长度不一致直接返回false
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])//每个字符逐一比较,不一致返回false
return false;
i++;
}
return true;//全部一样,返回true
}
}
return false;
}
5.clone()
protected native Object clone() throws CloneNotSupportedException;
在类中implements Cloneable,调用clone()返回的对象是一个独立的副本,两个对象地址不同,属性相同。protected 说明只能在本类中使用
6.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
将对象转成String类型,一般都会被重写
7.public final native void wait()、notify/notifyAll();
1、wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。
2、wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。
3、 由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说明当前线程一定是获取了锁的。
当线程执行wait()方法时候,会释放当前的锁,然后让出CPU,进入等待状态。
只有当 notify/notifyAll() 被执行时候,才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。
也就是说,notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。所以在编程中,尽量在使用了notify/notifyAll() 后立即退出临界区,以唤醒其他线程
4、wait() 需要被try catch包围,中断也可以使wait等待的线程唤醒。
5、notify 和wait 的顺序不能错,如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的。
6、notify 和 notifyAll的区别
notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。notifyAll 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。如果当前情况下有多个线程需要被唤醒,推荐使用notifyAll 方法。比如在生产者-消费者里面的使用,每次都需要唤醒所有的消费者或是生产者,以判断程序是否可以继续往下执行。
public class K {
//状态锁
private Object lock;
//条件变量
private int now,need;
public void produce(int num){
//同步
synchronized (lock){
//当前有的不满足需要,进行等待
while(now < need){
try {
//等待阻塞
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我被唤醒了!");
}
// 做其他的事情
}
}
}