Android JNI 普通方法和静态方法详解
文章目录
- [Android JNI 普通方法和静态方法详解](#Android JNI 普通方法和静态方法详解)
-
- 一、前言
- [二、Android JNI 普通方法和静态方法](#二、Android JNI 普通方法和静态方法)
- [1、native 的静态方法和普通方法](#1、native 的静态方法和普通方法)
-
-
- [(1) JNI定义nativie普通方法和静态方法](#(1) JNI定义nativie普通方法和静态方法)
- [(2)jni native-lib.cpp中的代码:](#(2)jni native-lib.cpp中的代码:)
- (3)调用JNI方法的代码
- Java中的普通方法和静态方法有以下区别:
- 2、cpp调用Java普通方法和静态方法区别
-
- [(1) Java定义普通方法和静态方法](#(1) Java定义普通方法和静态方法)
- [(2)jni native-lib.cpp中的代码:](#(2)jni native-lib.cpp中的代码:)
- (3)调用JNI方法的代码
-
- 三、其他
-
- [1、Android JNI 普通方法和静态方法小结](#1、Android JNI 普通方法和静态方法小结)
- [2、Android Jni的介绍和简单Demo实现](#2、Android Jni的介绍和简单Demo实现)
- [3、 Android JNI复杂用法,回调,C++中调用Java方法](#3、 Android JNI复杂用法,回调,C++中调用Java方法)
- [共勉: 今天很残酷,明天更残酷,后天很美好 ...](#共勉: 今天很残酷,明天更残酷,后天很美好 ...)
一、前言
Android Jni中Java的静态方法和普通方法有什么区别?
很多人可能都不清楚,如果想知道的可以了解一下。
比如下面一段代码:
//1、native 的静态方法和普通方法
public native void normalNativeMethod(); // 声明普通native方法
public static native void staticNativeMethod(); // 声明静态native方法
//2、Java 的普通方法和静态方法,C++调用过来的处理区别?
// 普通方法
public void normalMethod() {
System.out.println("这是一个普通方法");
}
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法");
}
JNI的静态方法包含native的静态方法,以及C++调用Java 的静态方法。
上面两种不同的静态方法,对于JNI来说有啥区别?
这个问题很少人会关注,一个是因为很少会静态方法调用JNI或者回调静态的Java方法;
另外一个是因为知道了或者调试过就不难了,所以很多人觉得没必要讲解和记录。
但是对于JNI 的初学者来说静态方法还是比较陌生的,很容易会懵逼的,不知道有啥区别。
本文主要讲解一下上面两种静态方法在JNI中的区别,有兴趣的可以看看。
二、Android JNI 普通方法和静态方法
1、native 的静态方法和普通方法
这个其实是很简单的,就是类里面的方法和对象的对象里面的方法的区别,这个和Java是完全一样的。
调用nativie的静态方法,只要类名就行,比如:MyClass.staticMethod();
调用nativie 的普通方法就要对象了,如果是本类就是隐藏的this,比如:myClass.method()。
并且Java中定义的nativie静态方法和普通写法,在cpp里面的写法都是一样的。
示例代码如下:
(1) JNI定义nativie普通方法和静态方法
public class MyJNIClass {
// 声明普通native方法
public native void normalNativeMethod();
// 声明静态native方法
public static native void staticNativeMethod();
static {
System.loadLibrary("myjni"); // 加载C++库
}
}
这里可以看到jni的库加载的代码就是在static里面的,
所以不管是静态方法还是普通方法都是不必担心库加载的问题。
(2)jni native-lib.cpp中的代码:
#include <jni.h>
extern "C" JNIEXPORT void JNICALL Java_com_example_myapp_MyJNIClass_normalNativeMethod(JNIEnv* env, jobject obj) {
// 在这里编写普通native方法的代码
}
extern "C"JNIEXPORT void JNICALL Java_com_example_myapp_MyJNIClass_staticNativeMethod(JNIEnv* env, jclass cls) {
// 在这里编写静态native方法的代码
}
对于cpp代码来说是一点区别都没有的,命名规则那些都是一样的。
(3)调用JNI方法的代码
在Android项目中的MainActivity中,调用这些JNI方法:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyJNIClass myJNI = new MyJNIClass();
// 调用普通native方法
myJNI.normalNativeMethod();
// 调用静态native方法
MyJNIClass.staticNativeMethod();
}
}
最大的区别就是调用的时候了,类和类的对象的区别。
所以native普通方法和静态方法,和Java的普通方法和静态方法是一样的,
就是调用的时候需要到的类和类的对象的区别,
静态方法需要类就可以调用,普通方法要类的对象才可以调用。
非要说点其他区别完整的,就把Java那套搬过去就行:
Java中的普通方法和静态方法有以下区别:
1、调用方式不同:
普通方法通过对象实例调用,而静态方法通过类名直接调用。
2、内存分配不同:
普通方法在每个对象实例中都有一份独立的内存空间,
而静态方法在类加载时就已经分配了内存空间,所有对象共享该方法。
3、访问权限不同:
普通方法可以访问类的所有成员(包括静态成员和非静态成员),而静态方法只能访问类的静态成员。
4、静态方法不能访问非静态成员:
由于静态方法在对象创建之前就已经存在,所以无法访问需要通过对象实例才能访问的非静态成员。
5、静态方法可以直接调用:
由于静态方法不依赖于对象实例,所以可以在没有创建对象的情况下直接调用。
6、静态方法不能被重写:
由于静态方法是通过类名直接调用的,所以无法被子类重写。
2、cpp调用Java普通方法和静态方法区别
先看一下下面的示例代码:
(1) Java定义普通方法和静态方法
public class MyJNIClass {
// 普通方法
public void normalMethod() {
System.out.println("这是一个普通方法");
}
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法");
}
}
这里就是一个最普通的Java类,定义了一个普通方法和静态方法。
后面cpp代码会调用Java代码,执行程序后就可以看到打印。
(2)jni native-lib.cpp中的代码:
#include <jni.h>
extern "C" JNIEXPORT void JNICALL Java_com_example_myapp_MainActivity_callNormalMethod(JNIEnv* env, jobject obj) {
// 获取MyJNIClass类
jclass cls = env->FindClass("com/example/myapp/MyJNIClass");
// 获取普通方法的方法ID
jmethodID methodId = env->GetMethodID(cls, "normalMethod", "()V");
// 创建MyJNIClass对象
jobject jniObj = env->AllocObject(cls);
// 调用普通方法
env->CallVoidMethod(jniObj, methodId);
}
extern "C" JNIEXPORT void JNICALL Java_com_example_myapp_MainActivity_callStaticMethod(JNIEnv* env, jobject obj) {
// 获取MyJNIClass类
jclass cls = env->FindClass("com/example/myapp/MyJNIClass");
// 获取静态方法的方法ID
jmethodID methodId = env->GetStaticMethodID(cls, "staticMethod", "()V");
// 调用静态方法
env->CallStaticVoidMethod(cls, methodId);
}
其实关键就在这里,静态方法和普通方法调用的api函数是不一样的;
具体区别:
1、获取方法签名的api函数不同
GetMethodID 是获取普通方法签名id的方法;GetStaticMethodID是获取静态方法签名id的方法;
2、需要的调用对象不同
静态方法使用类就可以调用,普通方法还有获取到类的对象
3、反射执行调用普通方法和静态方法的api函数不同
CallVoidMethod 是普通方法执行的api函数,CallStaticVoidMethod 是静态方法执行的api函数;
这里只是一个举例,如果不是void的方法,那么api函数是不同的,
比如调用一个返回Int的方法,反射调用的api函数就是 CallIntMethod,其他的方法以此类推
(3)调用JNI方法的代码
在Android项目中的MainActivity中,调用这些JNI方法:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("myjni"); // 加载C++库
}
public native void callNormalMethod();
public native void callStaticMethod();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 调用普通方法
callNormalMethod();
// 调用静态方法
callStaticMethod();
}
}
执行程序后,就可以看到 MyJNIClass 类里面的静态方法和普通方法的打印日志。
三、其他
1、Android JNI 普通方法和静态方法小结
Java中定义的普通native方法和静态nativie方法区别:
两种方法没啥太大区别,cpp代码的写法是一样的,
区别就是Java的普通方法和静态方法的区别,使用的时候需要的调用对象不同,
普通方法是类的对象进行调用,静态方法是类直接进行调用。
cpp调用Java普通方法和静态方法区别:
cpp代码里面的实现api函数不同,调用静态方法获取类,调用普通方法要获取类的对象,
静态方法的调用一般是api函数里面多了Static关键字。
本文的内容精华,就是上面几句。
理解一下,或者操作试试,就会更加印象深刻。
2、Android Jni的介绍和简单Demo实现
之前写的文章,包含了简单使用到的api函数
https://blog.csdn.net/wenzhi20102321/article/details/136291126
3、 Android JNI复杂用法,回调,C++中调用Java方法
JNI C++调用Java代码实现和相关知识 :
https://blog.csdn.net/wenzhi20102321/article/details/136419405