1:什么是本地方法
本地方法:
Native Method是本地方法的意思,非java编写,比如c/c++,一般用于操作底层的硬件。
在java中通过本地方法接口也就是带native修饰符的方法来调用本地方法。
public class NativesDemo
{
native public void Native( ) ;
}
如:Thread 中的 sleep方法就是本地方法
public static native void sleep(long millis) throws InterruptedException;
本地方法的作用:
当java应用需要与java外面的环境交互:
当java需要与一些底层系统如操作系统或某些硬件交换信息时的情况。
本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且无需了解java应用之外的细节。
当java应用需要与操作系统交互:
JVM支持着java语言本身和运行时库,它由一个解释器(解释字节码)和一些连接到本地代码的库组成。
但它毕竟不是一个完整的系统,它经常依赖于一些底层(underneath在下面的)系统的支持。
当进行以下操作时需要通过使用本地方法:
1:用java实现了jre的与底层系统的交互;
2:使用 用C写的部分JVM;
3:使用 一些java语言本身没有提供封装的操作系统的特性时
JVM怎样使Native Method跑起来:
当一个类第一次被使用到时,这个类的字节码会被加载到内存。
在这个被加载的字节码的入口维持着一个该类所有方法描述符的list,
这些方法描述符包含这样一些信息:方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。
如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。
这些实现在一些DLL文件内,但是它们会被操作系统加载到java程序的地址空间。
当一个带有本地方法的类被加载时,其相关的DLL并未被加载,因此指向方法实现的指针并不会被设置。
当本地方法被调用之前,这些DLL才会被加载,这是通过调用java.system.loadLibrary()实现的。
2:对象引用与对象
对象引用指向对象的过程:
//新建一个类
public class Demo{
//默认构造方法
public Demo{
}
}
//新建一个对象
Demo demo=new Demo();
新建一个对象的这一条语句,其实包括了四个动作:
1:右边的“new Demo”,是以Demo类为模板,在堆空间里创建一个Demo对象。(分配内存空间)
2:末尾的()意味着,在对象创建后,立即调用Demo类的构造函数,对刚生成的对象进行初始化。
3:左边的“Demo demo”创建了一个Demo类 的 对象引用(变量),它存放在栈空间中。
(用来指向Demo对象的对象引用(变量))。
4:“=”操作符使 对象引用(变量) 指向 刚创建的那个Demo对象。
//那么实际上面的 Demo demo=new Demo(); 可以换成以下代码:
//创建对象引用(变量)
Demo demo;
/*将对象引用(变量) 指向对象*/ //创建对象
demo= new Demo();
创建对象的过程
对象引用与对象的区别:
1:从对象引用出发:
一个对象引用
可以指向一个对象
可以不指向对象。
//一个对象引用
Demo demo;
//一个对象引用指向一个对象
demo=new Demo();
//创建对象引用,但是没有指向对象
Demo demo;
2:从对象出发:
一个对象
可以被一个对象引用 引用
可以被多个对象引用 引用
//一个对象引用
Demo demo;
//创建对象,并被一个对象引用指向
demo=new Demo();
//创建多个对象引用
Demo demo1,demo2,demo3;
demo1=new Demo();
//创建对象,并被多个对象引用指向
demo2=demo1;
demo3=demo2;
3:new String()究竟创建几个对象?
分析以下代码
//等价于下面两行代码
String str = new String("Hello World");
// 在常量池中
String temp = "Hello World";
// 在堆上
String str = new String(temp);
这段代码就创建了2个String对象,
temp指向于常量池中,str指向于堆上,
而str内部的temp(char value[]) 则指向常量池中的char value[];
假如就只有这一句String str = new String("Hello World")代码
如果此时常量池中,已经存在了"Hello World",
那么此时就只创建堆上str,而不会创建常量池中temp;(这里都是引用)
注意:所以此时答案就是1个。
public static void main(String[] args) {
//先检查运行时常量池是否存在该字符串
//如果存在则直接指向 地址相同
String str1 = "test";
String str2 = "test";
System.out.println(str1==str2);//true
//分别在堆上的不同地址
String str3 = new String("test");
String str4 = new String("test");
System.out.println(str3==str4);//false
//一个在运行时常量池 一个在堆上
System.out.println(str1==str3);//false
}
}