精华内容
下载资源
问答
  • Java JNI由浅入深(包括:Java和C++互ArrayList泛型对象参数) 我们知道Java一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先声明native修饰的方法(类似接口里面的方法),再由C/...
    Java JNI由浅入深(包括:Java和C++互传ArrayList泛型对象参数) 
     
             我们知道Java是一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先声明native修饰的方法(类似接口里面的方法),再由C/C++程序来实现(类似实现接口里的方法)。这样Java调用这些native方法就相当于调用了C/C++里面实现了的方法。通常我们把这种机制叫做JNI(Java NativeInterfac),即Java 本地编程接口 


              Android也同理,要学会在Android上进行NDK开发,首先我们到打好java JNI的基础。现在我们暂时把Android开发丢到一边先,试试在Java之下编译一个C动态链接库,再用Java程序调用。 



    1)先来个最简单的打印HelloWorld例子: 

    Java代码(HelloJni.java): 

    view plainprint? 

       1. import java.util.*;  
       2. public class HelloJni{  
       3.       
       4.     static{  
       5.         System.loadLibrary("hello");  
       6.     }  
       7.     public native static void sayHello();  
       8.     public static void main(String [] args)  
       9.     {  
      10.                 HelloJni.sayHello();  
      11.     }  
      12. }  

    import java.util.*; public class HelloJni{ static{ System.loadLibrary("hello"); } public native static void sayHello(); public static void main(String [] args) { HelloJni.sayHello(); } }  

    生成头文件(HelloJni.h): 

    先javac HelloJni.java编译你的Java源码,再javah–jni HelloJni生成所需的头文件 

    头文件内容是这样的: 

    view plainprint? 

       1. /* DO NOT EDIT THIS FILE - it is machine generated */  
       2. #include <jni.h>  
       3. /* Header for class HelloJni */  
       4. #ifndef _Included_HelloJni  
       5. #define _Included_HelloJni  
       6. #ifdef __cplusplus  
       7. extern "C" {  
       8. #endif  
       9. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
      10. #ifdef __cplusplus  
      11. }  
      12. #endif  
      13. #endif  

    /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloJni */ #ifndef _Included_HelloJni #define _Included_HelloJni #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif 


    实现头文件声明的方法(HelloJni.cpp) 


    view plainprint? 

       1. #include "HelloJni.h"  
       2. JNIEXPORT void JNICALL Java_HelloJni_sayHello(JNIEnv *env, jclass cls)  
       3. {  
       4.        printf("HelloWorld");  
       5. }  

    #include "HelloJni.h" JNIEXPORT void JNICALL Java_HelloJni_sayHello(JNIEnv *env, jclass cls) { printf("HelloWorld"); } 



    编译命令: g++ -I$JAVA_HOME/include-I$JAVA_HOME/include/linux HelloJni.cpp -shared -o libhello.so 

    命令参数解析:-I 是指引入java虚拟机的库的路径,-shared 是指编译成动态链接库(共享库) –o 输出文件名(注意,在Linux平台下的动态链接库有一个命名格式:“lib+库名+.so”在java代码里面loadLibrary的时候不要加lib前缀和.so后缀) 

    由于我这里把这个动态链接库编译放在当前目录下,所以还要设置环境变量LD_LIBRARY_PATH=该so动态链接库所在的目录,才能正常运行 



    #############################+++华丽的分割线+++########################### 


    2)好了,可以打印HelloWorld出来后,我们再深入一点点,传入一个int的数,在C/C++代码里面加1后返回。 



    Java代码(HelloJni.java): 

    view plainprint? 

       1. public class HelloJni{  
       2.         static{  
       3.                    System.loadLibrary("hello");  
       4.         }  
       5.         public static native void sayHello();  
       6.         public native int getInt();  
       7.         public native void setInt(int i);  
       8.         public static void main(String args[]){  
       9.         //      HelloJni.sayHello();  
      10.                  HelloJni hello = new HelloJni();  
      11.                  hello.setInt(2);  
      12.                  System.out.println(hello.getInt());  
      13.         }  
      14. }  

    public class HelloJni{ static{ System.loadLibrary("hello"); } public static native void sayHello(); public native int getInt(); public native void setInt(int i); public static void main(String args[]){ // HelloJni.sayHello(); HelloJni hello = new HelloJni(); hello.setInt(2); System.out.println(hello.getInt()); } } 

    生成头文件(HelloJni.h): 

    view plainprint? 

       1. /* DO NOT EDIT THIS FILE - it is machine generated */  
       2. #include <jni.h>  
       3. /* Header for class HelloJni */  
       4. #ifndef _Included_HelloJni  
       5. #define _Included_HelloJni  
       6. #ifdef __cplusplus  
       7. extern "C" {  
       8. #endif  
       9. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
      10. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
      11. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
      12. #ifdef __cplusplus  
      13. }  
      14. #endif  
      15. #endif  

    /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloJni */ #ifndef _Included_HelloJni #define _Included_HelloJni #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass); JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint); #ifdef __cplusplus } #endif #endif 

    实现头文件声明的方法(HelloJni.cpp) 

    view plainprint? 

       1. #include "HelloJni.h"  
       2. int i=1;  
       3. JNIEXPORT void JNICALL Java_HelloJni_sayHello  
       4.   (JNIEnv *env, jclass cls){  
       5.         printf("HelloWorld/n");  
       6. }  
       7. JNIEXPORT jint JNICALL Java_HelloJni_getInt  
       8.   (JNIEnv *env, jobject thiz){  
       9.         return i;  
      10. }  
      11. JNIEXPORT void JNICALL Java_HelloJni_setInt  
      12.   (JNIEnv *env, jobject thiz,jint ji){  
      13.         i = ji+1;  
      14. }  

    #include "HelloJni.h" int i=1; JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *env, jclass cls){ printf("HelloWorld/n"); } JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *env, jobject thiz){ return i; } JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *env, jobject thiz,jint ji){ i = ji+1; } 

    运行结果:打印2 


    3)只是传入简单的数据类型不爽,这次让C/C++生成个Java对象返回 



    Java代码:pojo实体类(User.java) 

    view plainprint? 

       1. public class User{  
       2.         private long id;  
       3.         private String userName;  
       4.         private boolean isMan;  
       5.         private int age;  
       6.         public User(){}  
       7.         public User(long id, String userName, boolean isMan, int age) {  
       8.                 super();  
       9.                 this.id = id;  
      10.                 this.userName = userName;  
      11.                 this.isMan = isMan;  
      12.                 this.age = age;  
      13.         }  
      14.         public long getId() {  
      15.                 return id;  
      16.         }  
      17.         public void setId(long id) {  
      18.                 this.id = id;  
      19.         }  
      20.         public String getUserName() {  
      21.                 return userName;  
      22.         }  
      23.         public void setUserName(String userName) {  
      24.                 this.userName = userName;  
      25.         }  
      26.         public boolean isMan() {  
      27.                 return isMan;  
      28.         }  
      29.         public void setMan(boolean isMan) {  
      30.                 this.isMan = isMan;  
      31.         }  
      32.         public int getAge() {  
      33.                 return age;  
      34.         }  
      35.         public void setAge(int age) {  
      36.                 this.age = age;  
      37.         }  
      38. }  

    public class User{ private long id; private String userName; private boolean isMan; private int age; public User(){} public User(long id, String userName, boolean isMan, int age) { super(); this.id = id; this.userName = userName; this.isMan = isMan; this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public boolean isMan() { return isMan; } public void setMan(boolean isMan) { this.isMan = isMan; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 

    Java代码(HelloJni.java): 

    view plainprint? 

       1. public class HelloJni{  
       2.         static{  
       3.                 System.loadLibrary("userbean");  
       4.         }  
       5.         public static native void sayHello();  
       6.         public native int getInt();  
       7.         public native void setInt(int i);  
       8.         public native void setUser(String userName);  
       9.         public native User getUser();  
      10.         public static void main(String args[]){  
      11.         //      HelloJni.sayHello();  
      12.                 HelloJni hello = new HelloJni();  
      13.         //      hello.setInt(2);  
      14.         //      System.out.println(hello.getInt());  
      15.                 hello.setUser("LiangYaotian");  
      16.                 User user = hello.getUser();  
      17.                 System.out.println("user from c/c++");  
      18.                 System.out.println("name:"+user.getUserName());  
      19.                 System.out.println("isMan?:"+user.isMan());  
      20.                 System.out.println("age:"+user.getAge());  
      21.         }  
      22. }  

    public class HelloJni{ static{ System.loadLibrary("userbean"); } public static native void sayHello(); public native int getInt(); public native void setInt(int i); public native void setUser(String userName); public native User getUser(); public static void main(String args[]){ // HelloJni.sayHello(); HelloJni hello = new HelloJni(); // hello.setInt(2); // System.out.println(hello.getInt()); hello.setUser("LiangYaotian"); User user = hello.getUser(); System.out.println("user from c/c++"); System.out.println("name:"+user.getUserName()); System.out.println("isMan?:"+user.isMan()); System.out.println("age:"+user.getAge()); } } 

    生成头文件(HelloJni.h): 

    view plainprint? 

       1. #include <jni.h>  
       2. /* Header for class HelloJni */  
       3. #ifndef _Included_HelloJni  
       4. #define _Included_HelloJni  
       5. #ifdef __cplusplus  
       6. extern "C" {  
       7. #endif  
       8. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
       9. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
      10. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
      11. JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);  
      12. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);  
      13. #ifdef __cplusplus  
      14. }  
      15. #endif  
      16. #endif  

    #include <jni.h> /* Header for class HelloJni */ #ifndef _Included_HelloJni #define _Included_HelloJni #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass); JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint); JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring); JNIEXPORT jobject JNICALL Java_HelloJni_getUser (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 

    实现头文件声明的方法(HelloJni.cpp) 

    view plainprint? 

       1. #include <iostream>  
       2. #include <stdio.h>  
       3. using namespace std;  
       4. int i=1;  
       5. jobject user;  
       6. JNIEXPORT void JNICALL Java_HelloJni_sayHello  
       7.   (JNIEnv *env, jclass cls){  
       8.         printf("HelloWorld/n");  
       9. }  
      10. JNIEXPORT jint JNICALL Java_HelloJni_getInt  
      11.   (JNIEnv *env, jobject thiz){  
      12.         return i;  
      13. }  
      14. JNIEXPORT void JNICALL Java_HelloJni_setInt  
      15.   (JNIEnv *env, jobject thiz,jint ji){  
      16.         i = ji+1;  
      17. }  
      18. JNIEXPORT void JNICALL Java_HelloJni_setUser  
      19.   (JNIEnv *env, jobject thiz, jstring name){  
      20.         jclass userClass = env->FindClass("User");  
      21.         jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V");  
      22.         jfieldID mId = env->GetFieldID(userClass,"id","J");  
      23.         jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;");  
      24.         jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z");  
      25.         jfieldID mAge = env->GetFieldID(userClass,"age","I");  
      26.         jobject userObject = env->NewObject(userClass,userMethod);  
      27.         env->SetObjectField(userObject,mUserName,name);  
      28.         env->SetLongField(userObject,mId,1001);  
      29.         env->SetBooleanField(userObject,mIsMan,1);  
      30.         env->SetIntField(userObject,mAge,21);  
      31.         user = userObject;  
      32. }  

    #include <iostream> #include <stdio.h> using namespace std; int i=1; jobject user; JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *env, jclass cls){ printf("HelloWorld/n"); } JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *env, jobject thiz){ return i; } JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *env, jobject thiz,jint ji){ i = ji+1; } JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *env, jobject thiz, jstring name){ jclass userClass = env->FindClass("User"); jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V"); jfieldID mId = env->GetFieldID(userClass,"id","J"); jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;"); jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z"); jfieldID mAge = env->GetFieldID(userClass,"age","I"); jobject userObject = env->NewObject(userClass,userMethod); env->SetObjectField(userObject,mUserName,name); env->SetLongField(userObject,mId,1001); env->SetBooleanField(userObject,mIsMan,1); env->SetIntField(userObject,mAge,21); user = userObject; } 





    4)有些同学可能会说:“返回个Java对象算什么啊,C/C++和Java之间互传复杂对象才好玩呢!”正所谓“不怕做不到,就怕想不到”,我们接着重构一下上面那个例子! 


    这次我们传包含有User对象的List到C/C++程序里面 


    Java代码(User.java) 

    同上。 

    Java代码(HelloJni.java) 

    view plainprint? 

       1. import java.util.*;  
       2. public class HelloJni{  
       3.         static{  
       4.                 System.loadLibrary("userbean");  
       5.         }  
       6.         public native int get();  
       7.         public native void set(int i);  
       8.         public native void setUser(String userName);  
       9.         public native User getUser();  
      10.         public native void setUserList(ArrayList<User> userList);  
      11.         public native ArrayList<User> getUserList();  
      12.         public static void main(String [] args)  
      13.         {  
      14.                 HelloJni hello = new HelloJni();  
      15.         //      hello.set(2);  
      16.         //      System.out.println(hello.get());  
      17.         /* 
      18.                 hello.setUser("LiangYaotian"); 
      19.                 User user = hello.getUser(); 
      20.                 System.out.println("user from c/c++"); 
      21.                 System.out.println("name:"+user.getUserName()); 
      22.                 System.out.println("isMan?:"+user.isMan()); 
      23.                 System.out.println("age:"+user.getAge()); 
      24.         */  
      25.                 ArrayList<User> userList = new ArrayList<User>();  
      26.                 for(int i=0;i<10;i++){  
      27.                         User u = new User((long)(1000+i),"LiangYaotian"+i,true,21);  
      28.                         userList.add(u);  
      29.                 }  
      30.                 hello.setUserList(userList);  
      31.                 userList = null;  
      32.                 userList = hello.getUserList();  
      33.                 System.out.println("ArrayList<User> construct from C++,then Java print it.....");  
      34.                 for(User u : userList){  
      35.                         System.out.println("id:"+u.getId()+"; name:"+u.getUserName());  
      36.                 }  
      37.         }  
      38. }  

    import java.util.*; public class HelloJni{ static{ System.loadLibrary("userbean"); } public native int get(); public native void set(int i); public native void setUser(String userName); public native User getUser(); public native void setUserList(ArrayList<User> userList); public native ArrayList<User> getUserList(); public static void main(String [] args) { HelloJni hello = new HelloJni(); // hello.set(2); // System.out.println(hello.get()); /* hello.setUser("LiangYaotian"); User user = hello.getUser(); System.out.println("user from c/c++"); System.out.println("name:"+user.getUserName()); System.out.println("isMan?:"+user.isMan()); System.out.println("age:"+user.getAge()); */ ArrayList<User> userList = new ArrayList<User>(); for(int i=0;i<10;i++){ User u = new User((long)(1000+i),"LiangYaotian"+i,true,21); userList.add(u); } hello.setUserList(userList); userList = null; userList = hello.getUserList(); System.out.println("ArrayList<User> construct from C++,then Java print it....."); for(User u : userList){ System.out.println("id:"+u.getId()+"; name:"+u.getUserName()); } } } 

    C头文件(HelloJni.h) 

    view plainprint? 

       1. #include <jni.h>  
       2. /* Header for class HelloJni */  
       3. #ifndef _Included_HelloJni  
       4. #define _Included_HelloJni  
       5. #ifdef __cplusplus  
       6. extern "C" {  
       7. #endif  
       8. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
       9. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
      10. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
      11. JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);  
      12. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);  

    #include <jni.h> /* Header for class HelloJni */ #ifndef _Included_HelloJni #define _Included_HelloJni #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass); JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint); JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring); JNIEXPORT jobject JNICALL Java_HelloJni_getUser (JNIEnv *, jobject); 

    头文件的实现(HelloJni.cpp) 

    view plainprint? 

       1. #include "HelloJni.h"  
       2. int i=1;  
       3. jobject user;  
       4. JNIEXPORT jint JNICALL Java_HelloJni_get  
       5.   (JNIEnv *env, jobject jthiz){  
       6.         printf("HelloWorld/n");  
       7. }  
       8. JNIEXPORT void JNICALL Java_HelloJni_set  
       9.   (JNIEnv *env, jobject jthiz, jint ji){  
      10.         i = ji+1;  
      11. }  
      12. JNIEXPORT void JNICALL Java_HelloJni_setUser  
      13.   (JNIEnv *env, jobject jthiz, jstring name){  
      14.         jclass userClass = env->FindClass("User");  
      15.         jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V");  
      16.         jfieldID mId = env->GetFieldID(userClass,"id","J");  
      17.         jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;");  
      18.         jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z");  
      19.         jfieldID mAge = env->GetFieldID(userClass,"age","I");  
      20.         jobject userObject = env->NewObject(userClass,userMethod);  
      21.         env->SetObjectField(userObject,mUserName,name);  
      22.         env->SetLongField(userObject,mId,1001);  
      23.         env->SetBooleanField(userObject,mIsMan,1);  
      24.         env->SetIntField(userObject,mAge,21);  
      25.         user = userObject;  
      26. }  
      27. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  
      28.   (JNIEnv *env, jobject jthiz){  
      29.         return user;  
      30. }  
      31. JNIEXPORT void JNICALL Java_HelloJni_setUserList  
      32.   (JNIEnv *env, jobject jthiz, jobject userList){  
      33.         int i;  
      34.         //class ArrayList  
      35.         jclass cls_arraylist = env->GetObjectClass(userList);  
      36.         //method in class ArrayList  
      37.         jmethodID arraylist_get = env->GetMethodID(cls_arraylist,"get","(I)Ljava/lang/Object;");  
      38.         jmethodID arraylist_size = env->GetMethodID(cls_arraylist,"size","()I");  
      39.         jint len = env->CallIntMethod(userList,arraylist_size);  
      40.         printf("get java ArrayList<User> object by C++ , then print it...../n");  
      41.         for(i=0;i<len;i++){  
      42.                 jobject obj_user = env->CallObjectMethod(userList,arraylist_get,i);  
      43.                 jclass cls_user = env->GetObjectClass(obj_user);  
      44.                 jmethodID user_getId = env->GetMethodID(cls_user,"getId","()J");  
      45.                 jmethodID user_getUserName = env->GetMethodID(cls_user,"getUserName","()Ljava/lang/String;");  
      46.                 jmethodID user_isMan = env->GetMethodID(cls_user,"isMan","()Z");  
      47.                 jmethodID user_getAge = env->GetMethodID(cls_user,"getAge","()I");  
      48.                 jstring name = (jstring)env->CallObjectMethod(obj_user,user_getUserName);  
      49.                 jboolean b = true;  
      50.                 const char *namePtr = env->GetStringUTFChars(name,&b);  
      51.                 jlong id = env->CallLongMethod(obj_user,user_getId);  
      52.                 jboolean sex = env->CallBooleanMethod(obj_user,user_isMan);  
      53.                 jint age = env->CallIntMethod(obj_user,user_getAge);  
      54.                 printf("Id:%d; ",id);  
      55.                 printf("Name:%s; ",namePtr);  
      56.                 printf("isMan? %d; ",sex);  
      57.                 printf("Age:%d /n ",age);  
      58.         }  
      59. }  
      60. JNIEXPORT jobject JNICALL Java_HelloJni_getUserList  
      61.   (JNIEnv *env, jobject jthiz){  
      62.         //ArrayList Object  
      63.         jclass cls_ArrayList = env->FindClass("java/util/ArrayList");  
      64.         jmethodID construct = env->GetMethodID(cls_ArrayList,"<init>","()V");  
      65.         jobject obj_ArrayList = env->NewObject(cls_ArrayList,construct,"");  
      66.         jmethodID arrayList_add = env->GetMethodID(cls_ArrayList,"add","(Ljava/lang/Object;)Z");  
      67.         //User Object  
      68.         jclass cls_user = env->FindClass("User");  
      69.         //none argument construct function  
      70.         jmethodID construct_user = env->GetMethodID(cls_user,"<init>","()V");  
      71.         //new a object  
      72.         jobject obj_user = env->NewObject(cls_user,construct_user,"");  
      73.         //get method id  
      74.         /* 
      75.         jmethodID user_setId = env->GetMethodID(cls_user,"setId","(J)V"); 
      76.         jmethodID user_setUserName = env->GetMethodID(cls_user,"setUserName","(Ljava/lang/String;)V"); 
      77.         jmethodID user_setMan = env->GetMethodID(cls_user,"setMan","(Z)V"); 
      78.         jmethodID user_setAge = env->GetMethodID(cls_user,"setAge","(I)V"); 
      79.         */  
      80.         int i;  
      81.         for(i=0;i<10;i++){  
      82.         //new a object  
      83.         jobject obj_user = env->NewObject(cls_user,construct_user,"");  
      84.         //get field id  
      85.         jfieldID user_id = env->GetFieldID(cls_user,"id","J");  
      86.         jfieldID user_name = env->GetFieldID(cls_user,"userName","Ljava/lang/String;");  
      87.         jfieldID user_isMan = env->GetFieldID(cls_user,"isMan","Z");  
      88.         jfieldID user_age = env->GetFieldID(cls_user,"age","I");  
      89.         env->SetLongField(obj_user,user_id,i);  
      90.         env->SetObjectField(obj_user,user_name,env->NewStringUTF("LiangYaoTian"));  
      91.         env->SetBooleanField(obj_user,user_isMan,1);  
      92.         env->SetIntField(obj_user,user_age,21);  
      93.                 env->CallObjectMethod(obj_ArrayList,arrayList_add,obj_user);  
      94.         }  
      95.         return obj_ArrayList;  
      96. }  

    #include "HelloJni.h" int i=1; jobject user; JNIEXPORT jint JNICALL Java_HelloJni_get (JNIEnv *env, jobject jthiz){ printf("HelloWorld/n"); } JNIEXPORT void JNICALL Java_HelloJni_set (JNIEnv *env, jobject jthiz, jint ji){ i = ji+1; } JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *env, jobject jthiz, jstring name){ jclass userClass = env->FindClass("User"); jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V"); jfieldID mId = env->GetFieldID(userClass,"id","J"); jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;"); jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z"); jfieldID mAge = env->GetFieldID(userClass,"age","I"); jobject userObject = env->NewObject(userClass,userMethod); env->SetObjectField(userObject,mUserName,name); env->SetLongField(userObject,mId,1001); env->SetBooleanField(userObject,mIsMan,1); env->SetIntField(userObject,mAge,21); user = userObject; } JNIEXPORT jobject JNICALL Java_HelloJni_getUser (JNIEnv *env, jobject jthiz){ return user; } JNIEXPORT void JNICALL Java_HelloJni_setUserList (JNIEnv *env, jobject jthiz, jobject userList){ int i; //class ArrayList jclass cls_arraylist = env->GetObjectClass(userList); //method in class ArrayList jmethodID arraylist_get = env->GetMethodID(cls_arraylist,"get","(I)Ljava/lang/Object;"); jmethodID arraylist_size = env->GetMethodID(cls_arraylist,"size","()I"); jint len = env->CallIntMethod(userList,arraylist_size); printf("get java ArrayList<User> object by C++ , then print it...../n"); for(i=0;i<len;i++){ jobject obj_user = env->CallObjectMethod(userList,arraylist_get,i); jclass cls_user = env->GetObjectClass(obj_user); jmethodID user_getId = env->GetMethodID(cls_user,"getId","()J"); jmethodID user_getUserName = env->GetMethodID(cls_user,"getUserName","()Ljava/lang/String;"); jmethodID user_isMan = env->GetMethodID(cls_user,"isMan","()Z"); jmethodID user_getAge = env->GetMethodID(cls_user,"getAge","()I"); jstring name = (jstring)env->CallObjectMethod(obj_user,user_getUserName); jboolean b = true; const char *namePtr = env->GetStringUTFChars(name,&b); jlong id = env->CallLongMethod(obj_user,user_getId); jboolean sex = env->CallBooleanMethod(obj_user,user_isMan); jint age = env->CallIntMethod(obj_user,user_getAge); printf("Id:%d; ",id); printf("Name:%s; ",namePtr); printf("isMan? %d; ",sex); printf("Age:%d /n ",age); } } JNIEXPORT jobject JNICALL Java_HelloJni_getUserList (JNIEnv *env, jobject jthiz){ //ArrayList Object jclass cls_ArrayList = env->FindClass("java/util/ArrayList"); jmethodID construct = env->GetMethodID(cls_ArrayList,"<init>","()V"); jobject obj_ArrayList = env->NewObject(cls_ArrayList,construct,""); jmethodID arrayList_add = env->GetMethodID(cls_ArrayList,"add","(Ljava/lang/Object;)Z"); //User Object jclass cls_user = env->FindClass("User"); //none argument construct function jmethodID construct_user = env->GetMethodID(cls_user,"<init>","()V"); //new a object jobject obj_user = env->NewObject(cls_user,construct_user,""); //get method id /* jmethodID user_setId = env->GetMethodID(cls_user,"setId","(J)V"); jmethodID user_setUserName = env->GetMethodID(cls_user,"setUserName","(Ljava/lang/String;)V"); jmethodID user_setMan = env->GetMethodID(cls_user,"setMan","(Z)V"); jmethodID user_setAge = env->GetMethodID(cls_user,"setAge","(I)V"); */ int i; for(i=0;i<10;i++){ //new a object jobject obj_user = env->NewObject(cls_user,construct_user,""); //get field id jfieldID user_id = env->GetFieldID(cls_user,"id","J"); jfieldID user_name = env->GetFieldID(cls_user,"userName","Ljava/lang/String;"); jfieldID user_isMan = env->GetFieldID(cls_user,"isMan","Z"); jfieldID user_age = env->GetFieldID(cls_user,"age","I"); env->SetLongField(obj_user,user_id,i); env->SetObjectField(obj_user,user_name,env->NewStringUTF("LiangYaoTian")); env->SetBooleanField(obj_user,user_isMan,1); env->SetIntField(obj_user,user_age,21); env->CallObjectMethod(obj_ArrayList,arrayList_add,obj_user); } return obj_ArrayList; } 

    运行结果: 

    theEnd.jpg 





    源码:E-Mail我:u_xtian@qq.com 

    原创作品,转载需注明出处...http://blog.csdn.net/u_xtian/archive/2010/11/25/6033963.aspx 
    展开全文
  • 我们知道Java一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先声明native修饰的方法(类似接口里面的方法),再由C/C++程序来实现(类似实现接口里的方法)。这样Java调用这些native...

    我们知道Java是一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先声明native修饰的方法(类似接口里面的方法),再由C/C++程序来实现(类似实现接口里的方法)。这样Java调用这些native方法就相当于调用了C/C++里面实现了的方法。通常我们把这种机制叫做JNI(Java NativeInterfac),即Java 本地编程接口


              Android也同理,要学会在Android上进行NDK开发,首先我们到打好java JNI的基础。现在我们暂时把Android开发丢到一边先,试试在Java之下编译一个C动态链接库,再用Java程序调用。

     

    1)先来个最简单的打印HelloWorld例子:

    Java代码(HelloJni.java)

    [java] view plaincopy
    1. import java.util.*;  
    2. public class HelloJni{  
    3.       
    4.     static{  
    5.         System.loadLibrary("hello");  
    6.     }  
    7.     public native static void sayHello();  
    8.     public static void main(String [] args)  
    9.     {  
    10.                 HelloJni.sayHello();  
    11.     }  
    12. }  
     

    生成头文件(HelloJni.h):

    javac HelloJni.java编译你的Java源码,再javah–jni HelloJni生成所需的头文件

    头文件内容是这样的:

    [java] view plaincopy
    1. /* DO NOT EDIT THIS FILE - it is machine generated */  
    2. #include <jni.h>  
    3. /* Header for class HelloJni */  
    4. #ifndef _Included_HelloJni  
    5. #define _Included_HelloJni  
    6. #ifdef __cplusplus  
    7. extern "C" {  
    8. #endif  
    9. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
    10. #ifdef __cplusplus  
    11. }  
    12. #endif  
    13. #endif  
     


    实现头文件声明的方法(HelloJni.cpp)


    [c-sharp] view plaincopy
    1. #include "HelloJni.h"  
    2. JNIEXPORT void JNICALL Java_HelloJni_sayHello(JNIEnv *env, jclass cls)  
    3. {  
    4.        printf("HelloWorld");  
    5. }  
     

     

    编译命令g++ -I$JAVA_HOME/include-I$JAVA_HOME/include/linux HelloJni.cpp -shared -o libhello.so

    命令参数解析:-I 是指引入java虚拟机的库的路径,-shared 是指编译成动态链接库(共享库) –o 输出文件名(注意,在Linux平台下的动态链接库有一个命名格式:“lib+库名+.so”在java代码里面loadLibrary的时候不要加lib前缀和.so后缀)

    由于我这里把这个动态链接库编译放在当前目录下,所以还要设置环境变量LD_LIBRARY_PATH=so动态链接库所在的目录,才能正常运行

     

    #############################+++华丽的分割线+++###########################


    2)好了,可以打印HelloWorld出来后,我们再深入一点点,传入一个int的数,在C/C++代码里面加1后返回。

     

    Java代码(HelloJni.java)

    [java] view plaincopy
    1. public class HelloJni{  
    2.         static{  
    3.                    System.loadLibrary("hello");  
    4.         }  
    5.         public static native void sayHello();  
    6.         public native int getInt();  
    7.         public native void setInt(int i);  
    8.         public static void main(String args[]){  
    9.         //      HelloJni.sayHello();  
    10.                  HelloJni hello = new HelloJni();  
    11.                  hello.setInt(2);  
    12.                  System.out.println(hello.getInt());  
    13.         }  
    14. }  
     

    生成头文件(HelloJni.h):

    [c-sharp] view plaincopy
    1. /* DO NOT EDIT THIS FILE - it is machine generated */  
    2. #include <jni.h>  
    3. /* Header for class HelloJni */  
    4. #ifndef _Included_HelloJni  
    5. #define _Included_HelloJni  
    6. #ifdef __cplusplus  
    7. extern "C" {  
    8. #endif  
    9. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
    10. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
    11. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
    12. #ifdef __cplusplus  
    13. }  
    14. #endif  
    15. #endif  
     

    实现头文件声明的方法(HelloJni.cpp)

    [java] view plaincopy
    1. #include "HelloJni.h"  
    2. int i=1;  
    3. JNIEXPORT void JNICALL Java_HelloJni_sayHello  
    4.   (JNIEnv *env, jclass cls){  
    5.         printf("HelloWorld/n");  
    6. }  
    7. JNIEXPORT jint JNICALL Java_HelloJni_getInt  
    8.   (JNIEnv *env, jobject thiz){  
    9.         return i;  
    10. }  
    11. JNIEXPORT void JNICALL Java_HelloJni_setInt  
    12.   (JNIEnv *env, jobject thiz,jint ji){  
    13.         i = ji+1;  
    14. }  
     

    运行结果:打印2


    3)只是传入简单的数据类型不爽,这次让C/C++生成个Java对象返回

     

    Java代码:pojo实体类(User.java)

    [c-sharp] view plaincopy
    1. public class User{  
    2.         private long id;  
    3.         private String userName;  
    4.         private boolean isMan;  
    5.         private int age;  
    6.         public User(){}  
    7.         public User(long id, String userName, boolean isMan, int age) {  
    8.                 super();  
    9.                 this.id = id;  
    10.                 this.userName = userName;  
    11.                 this.isMan = isMan;  
    12.                 this.age = age;  
    13.         }  
    14.         public long getId() {  
    15.                 return id;  
    16.         }  
    17.         public void setId(long id) {  
    18.                 this.id = id;  
    19.         }  
    20.         public String getUserName() {  
    21.                 return userName;  
    22.         }  
    23.         public void setUserName(String userName) {  
    24.                 this.userName = userName;  
    25.         }  
    26.         public boolean isMan() {  
    27.                 return isMan;  
    28.         }  
    29.         public void setMan(boolean isMan) {  
    30.                 this.isMan = isMan;  
    31.         }  
    32.         public int getAge() {  
    33.                 return age;  
    34.         }  
    35.         public void setAge(int age) {  
    36.                 this.age = age;  
    37.         }  
    38. }  
     

    Java代码(HelloJni.java)

    [java] view plaincopy
    1. public class HelloJni{  
    2.         static{  
    3.                 System.loadLibrary("userbean");  
    4.         }  
    5.         public static native void sayHello();  
    6.         public native int getInt();  
    7.         public native void setInt(int i);  
    8.         public native void setUser(String userName);  
    9.         public native User getUser();  
    10.         public static void main(String args[]){  
    11.         //      HelloJni.sayHello();  
    12.                 HelloJni hello = new HelloJni();  
    13.         //      hello.setInt(2);  
    14.         //      System.out.println(hello.getInt());  
    15.                 hello.setUser("LiangYaotian");  
    16.                 User user = hello.getUser();  
    17.                 System.out.println("user from c/c++");  
    18.                 System.out.println("name:"+user.getUserName());  
    19.                 System.out.println("isMan?:"+user.isMan());  
    20.                 System.out.println("age:"+user.getAge());  
    21.         }  
    22. }  
     

    生成头文件(HelloJni.h):

    [c-sharp] view plaincopy
    1. #include <jni.h>  
    2. /* Header for class HelloJni */  
    3. #ifndef _Included_HelloJni  
    4. #define _Included_HelloJni  
    5. #ifdef __cplusplus  
    6. extern "C" {  
    7. #endif  
    8. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
    9. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
    10. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
    11. JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);  
    12. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);  
    13. #ifdef __cplusplus  
    14. }  
    15. #endif  
    16. #endif  
     

    实现头文件声明的方法(HelloJni.cpp)

    [c-sharp] view plaincopy
    1. #include <iostream>  
    2. #include <stdio.h>  
    3. using namespace std;  
    4. int i=1;  
    5. jobject user;  
    6. JNIEXPORT void JNICALL Java_HelloJni_sayHello  
    7.   (JNIEnv *env, jclass cls){  
    8.         printf("HelloWorld/n");  
    9. }  
    10. JNIEXPORT jint JNICALL Java_HelloJni_getInt  
    11.   (JNIEnv *env, jobject thiz){  
    12.         return i;  
    13. }  
    14. JNIEXPORT void JNICALL Java_HelloJni_setInt  
    15.   (JNIEnv *env, jobject thiz,jint ji){  
    16.         i = ji+1;  
    17. }  
    18. JNIEXPORT void JNICALL Java_HelloJni_setUser  
    19.   (JNIEnv *env, jobject thiz, jstring name){  
    20.         jclass userClass = env->FindClass("User");  
    21.         jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V");  
    22.         jfieldID mId = env->GetFieldID(userClass,"id","J");  
    23.         jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;");  
    24.         jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z");  
    25.         jfieldID mAge = env->GetFieldID(userClass,"age","I");  
    26.         jobject userObject = env->NewObject(userClass,userMethod);  
    27.         env->SetObjectField(userObject,mUserName,name);  
    28.         env->SetLongField(userObject,mId,1001);  
    29.         env->SetBooleanField(userObject,mIsMan,1);  
    30.         env->SetIntField(userObject,mAge,21);  
    31.         user = userObject;  
    32. }  
     

     

     

    4)有些同学可能会说:“返回个Java对象算什么啊,C/C++和Java之间互传复杂对象才好玩呢!”正所谓“不怕做不到,就怕想不到”,我们接着重构一下上面那个例子!


    这次我们传包含有User对象的List到C/C++程序里面


    Java代码(User.java)

    同上。

    Java代码(HelloJni.java)

    [java] view plaincopy
    1. import java.util.*;  
    2. public class HelloJni{  
    3.         static{  
    4.                 System.loadLibrary("userbean");  
    5.         }  
    6.         public native int get();  
    7.         public native void set(int i);  
    8.         public native void setUser(String userName);  
    9.         public native User getUser();  
    10.         public native void setUserList(ArrayList<User> userList);  
    11.         public native ArrayList<User> getUserList();  
    12.         public static void main(String [] args)  
    13.         {  
    14.                 HelloJni hello = new HelloJni();  
    15.         //      hello.set(2);  
    16.         //      System.out.println(hello.get());  
    17.         /* 
    18.                 hello.setUser("LiangYaotian"); 
    19.                 User user = hello.getUser(); 
    20.                 System.out.println("user from c/c++"); 
    21.                 System.out.println("name:"+user.getUserName()); 
    22.                 System.out.println("isMan?:"+user.isMan()); 
    23.                 System.out.println("age:"+user.getAge()); 
    24.         */  
    25.                 ArrayList<User> userList = new ArrayList<User>();  
    26.                 for(int i=0;i<10;i++){  
    27.                         User u = new User((long)(1000+i),"LiangYaotian"+i,true,21);  
    28.                         userList.add(u);  
    29.                 }  
    30.                 hello.setUserList(userList);  
    31.                 userList = null;  
    32.                 userList = hello.getUserList();  
    33.                 System.out.println("ArrayList<User> construct from C++,then Java print it.....");  
    34.                 for(User u : userList){  
    35.                         System.out.println("id:"+u.getId()+"; name:"+u.getUserName());  
    36.                 }  
    37.         }  
    38. }  
     

    C头文件(HelloJni.h)

    [java] view plaincopy
    1. #include <jni.h>  
    2. /* Header for class HelloJni */  
    3. #ifndef _Included_HelloJni  
    4. #define _Included_HelloJni  
    5. #ifdef __cplusplus  
    6. extern "C" {  
    7. #endif  
    8. JNIEXPORT void JNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);  
    9. JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);  
    10. JNIEXPORT void JNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);  
    11. JNIEXPORT void JNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);  
    12. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);  
     

    头文件的实现(HelloJni.cpp)

    [java] view plaincopy
    1. #include "HelloJni.h"  
    2. int i=1;  
    3. jobject user;  
    4. JNIEXPORT jint JNICALL Java_HelloJni_get  
    5.   (JNIEnv *env, jobject jthiz){  
    6.         printf("HelloWorld/n");  
    7. }  
    8. JNIEXPORT void JNICALL Java_HelloJni_set  
    9.   (JNIEnv *env, jobject jthiz, jint ji){  
    10.         i = ji+1;  
    11. }  
    12. JNIEXPORT void JNICALL Java_HelloJni_setUser  
    13.   (JNIEnv *env, jobject jthiz, jstring name){  
    14.         jclass userClass = env->FindClass("User");  
    15.         jmethodID userMethod = env->GetMethodID(userClass,"<init>","()V");  
    16.         jfieldID mId = env->GetFieldID(userClass,"id","J");  
    17.         jfieldID mUserName = env->GetFieldID(userClass,"userName","Ljava/lang/String;");  
    18.         jfieldID mIsMan = env->GetFieldID(userClass,"isMan","Z");  
    19.         jfieldID mAge = env->GetFieldID(userClass,"age","I");  
    20.         jobject userObject = env->NewObject(userClass,userMethod);  
    21.         env->SetObjectField(userObject,mUserName,name);  
    22.         env->SetLongField(userObject,mId,1001);  
    23.         env->SetBooleanField(userObject,mIsMan,1);  
    24.         env->SetIntField(userObject,mAge,21);  
    25.         user = userObject;  
    26. }  
    27. JNIEXPORT jobject JNICALL Java_HelloJni_getUser  
    28.   (JNIEnv *env, jobject jthiz){  
    29.         return user;  
    30. }  
    31. JNIEXPORT void JNICALL Java_HelloJni_setUserList  
    32.   (JNIEnv *env, jobject jthiz, jobject userList){  
    33.         int i;  
    34.         //class ArrayList  
    35.         jclass cls_arraylist = env->GetObjectClass(userList);  
    36.         //method in class ArrayList  
    37.         jmethodID arraylist_get = env->GetMethodID(cls_arraylist,"get","(I)Ljava/lang/Object;");  
    38.         jmethodID arraylist_size = env->GetMethodID(cls_arraylist,"size","()I");  
    39.         jint len = env->CallIntMethod(userList,arraylist_size);  
    40.         printf("get java ArrayList<User> object by C++ , then print it...../n");  
    41.         for(i=0;i<len;i++){  
    42.                 jobject obj_user = env->CallObjectMethod(userList,arraylist_get,i);  
    43.                 jclass cls_user = env->GetObjectClass(obj_user);  
    44.                 jmethodID user_getId = env->GetMethodID(cls_user,"getId","()J");  
    45.                 jmethodID user_getUserName = env->GetMethodID(cls_user,"getUserName","()Ljava/lang/String;");  
    46.                 jmethodID user_isMan = env->GetMethodID(cls_user,"isMan","()Z");  
    47.                 jmethodID user_getAge = env->GetMethodID(cls_user,"getAge","()I");  
    48.                 jstring name = (jstring)env->CallObjectMethod(obj_user,user_getUserName);  
    49.                 jboolean b = true;  
    50.                 const char *namePtr = env->GetStringUTFChars(name,&b);  
    51.                 jlong id = env->CallLongMethod(obj_user,user_getId);  
    52.                 jboolean sex = env->CallBooleanMethod(obj_user,user_isMan);  
    53.                 jint age = env->CallIntMethod(obj_user,user_getAge);  
    54.                 printf("Id:%d; ",id);  
    55.                 printf("Name:%s; ",namePtr);  
    56.                 printf("isMan? %d; ",sex);  
    57.                 printf("Age:%d /n ",age);  
    58.         }  
    59. }  
    60. JNIEXPORT jobject JNICALL Java_HelloJni_getUserList  
    61.   (JNIEnv *env, jobject jthiz){  
    62.         //ArrayList Object  
    63.         jclass cls_ArrayList = env->FindClass("java/util/ArrayList");  
    64.         jmethodID construct = env->GetMethodID(cls_ArrayList,"<init>","()V");  
    65.         jobject obj_ArrayList = env->NewObject(cls_ArrayList,construct,"");  
    66.         jmethodID arrayList_add = env->GetMethodID(cls_ArrayList,"add","(Ljava/lang/Object;)Z");  
    67.         //User Object  
    68.         jclass cls_user = env->FindClass("User");  
    69.         //none argument construct function  
    70.         jmethodID construct_user = env->GetMethodID(cls_user,"<init>","()V");  
    71.         //new a object  
    72.         jobject obj_user = env->NewObject(cls_user,construct_user,"");  
    73.         //get method id  
    74.         /* 
    75.         jmethodID user_setId = env->GetMethodID(cls_user,"setId","(J)V"); 
    76.         jmethodID user_setUserName = env->GetMethodID(cls_user,"setUserName","(Ljava/lang/String;)V"); 
    77.         jmethodID user_setMan = env->GetMethodID(cls_user,"setMan","(Z)V"); 
    78.         jmethodID user_setAge = env->GetMethodID(cls_user,"setAge","(I)V"); 
    79.         */  
    80.         int i;  
    81.         for(i=0;i<10;i++){  
    82.         //new a object  
    83.         jobject obj_user = env->NewObject(cls_user,construct_user,"");  
    84.         //get field id  
    85.         jfieldID user_id = env->GetFieldID(cls_user,"id","J");  
    86.         jfieldID user_name = env->GetFieldID(cls_user,"userName","Ljava/lang/String;");  
    87.         jfieldID user_isMan = env->GetFieldID(cls_user,"isMan","Z");  
    88.         jfieldID user_age = env->GetFieldID(cls_user,"age","I");  
    89.         env->SetLongField(obj_user,user_id,i);  
    90.         env->SetObjectField(obj_user,user_name,env->NewStringUTF("LiangYaoTian"));  
    91.         env->SetBooleanField(obj_user,user_isMan,1);  
    92.         env->SetIntField(obj_user,user_age,21);  
    93.                 env->CallObjectMethod(obj_ArrayList,arrayList_add,obj_user);  
    94.         }  
    95.         return obj_ArrayList;  
    96. }  

    展开全文
  • 方法调用的时候,有时候需要传一个Class<T>泛型过来。 但是,有时候,传过来的Class又是泛型。 比如下面代码 List<User> 这时,传过去的只能是 List.class 此时就达不到我们想要的类型...

    在方法调用的时候,有时候需要传一个Class<T>泛型过来。

    但是,有时候,传过来的Class又是泛型。

    比如下面代码

    List<User>

    这时,传过去的只能是

    List.class

    此时就达不到我们想要的类型,List<User>的效果。

    在这里只要实现一个类就可以获取到List<User>

    public class DefaultTargetType<T> {
    
        private Type type;
        private Class<T> classType;
    
        @SuppressWarnings("unchecked")
        public DefaultTargetType() {
            Type superClass = getClass().getGenericSuperclass();
            this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
            if (this.type instanceof ParameterizedType) {
                this.classType = (Class<T>) ((ParameterizedType) this.type).getRawType();
            } else {
                this.classType = (Class<T>) this.type;
            }
        }
    }

    结果:

    Class<List<User>> classType = new DefaultTargetType<List<User>>() {}.getClassType();

    就可以获取到泛型中的类型了。

     

    作者:Se7end

    声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接。

     

    转载于:https://www.cnblogs.com/se7end/p/11248540.html

    展开全文
  • 对于这个方法一个java泛型方法,两个参数:的一个是Sql语句,第二个javaBean对象! 主要功能就是SQL语句,随便javaBean的对象,要和数据库进行连接,javaBean里的字段要和数据库里的列进行比较,不管是传入什么什么...
  • Java泛型

    2019-12-07 14:54:02
    比如一个方法如果接收List<Object>作为形式参数,那么如果尝试将一个List<String>的对象作为实际参数进去,却发现无法通过编译。虽然从直觉上来说,Object是String的父类,这种类型转换应该是合理的。...

    Java泛型

    开发人员在使用泛型的时候,很容易根据自己的直觉而犯一些错误。比如一个方法如果接收List<Object>作为形式参数,那么如果尝试将一个List<String>的对象作为实际参数传进去,却发现无法通过编译。虽然从直觉上来说,ObjectString的父类,这种类型转换应该是合理的。但是实际上这会产生隐含的类型转换问题,因此编译器直接就禁止这样的行为

    类型擦除

    Java中的泛型基本上都是在编译器这个层次来实现的,在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉,这个过程就称为类型擦除。如在代码中定义的List<Object>List<String>等类型,在编译之后都会变成ListJVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。

    很多泛型的奇怪特性都与这个类型擦除的存在有关,包括:

    • 泛型类并没有自己独有的Class类对象。比如并不存在List<String>.class或是List<Integer>.class,而只有List.class

    • 静态变量是被泛型类的所有实例所共享的。对于声明为MyClass<T>的类,访问其中的静态变量的方法仍然是 MyClass.myStaticVar。不管是通过new MyClass<String>还是new MyClass<Integer>创建的对象,都是共享一个静态变量。

    • 泛型的类型参数不能用在Java异常处理的catch语句中。因为异常处理是由JVM在运行时刻来进行的。由于类型信息被擦除,JVM是无法区分两个异常类型MyException<String>MyException<Integer>的。对于JVM来说,它们都是 MyException类型的。也就无法执行与异常对应的catch语句。

    类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般是Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换成具体的类。同时去掉出现的类型声明,即去掉<>的内容。比如T get()方法声明就变成了Object get()List<String>就变成了List。接下来就可能需要生成一些桥接方法(bridge method)。这是由于擦除了类型之后的类可能缺少某些必须的方法。比如考虑下面的代码:

      class MyString implements Comparable<String> {
          public int compareTo(String str) {        
              return 0;    
          }
      }
    

    当类型信息被擦除之后,上述类的声明变成了class MyString implements Comparable。但是这样的话,类MyString就会有编译错误,因为没有实现接口Comparable声明的int compareTo(Object)方法。这个时候就由编译器来动态生成这个方法。

    通配符

    在使用泛型类的时候,既可以指定一个具体的类型,如List<String>就声明了具体的类型是String;也可以用通配符?来表示未知类型,如List<?>就声明了List中包含的元素类型是未知的。 通配符所代表的其实是一组类型,但具体的类型是未知的。List<?>所声明的就是所有类型都是可以的。但是List<?>并不等同于List<Object>List<Object>实际上确定了List中包含的是Object及其子类,在使用的时候都可以通过Object来进行引用。而List<?>则其中所包含的元素类型是不确定。其中可能包含的是String,也可能是 Integer。如果它包含了String的话,往里面添加Integer类型的元素就是错误的。正因为类型未知,就不能通过new ArrayList<?>()的方法来创建一个新的ArrayList对象。因为编译器无法知道具体的类型是什么。但是对于 List<?>中的元素确总是可以用Object来引用的,因为虽然类型未知,但肯定是Object及其子类。考虑下面的代码:

    public void wildcard(List<?> list) {
        list.add(1);//编译错误
    }  
    

    如上所示,试图对一个带通配符的泛型类进行操作的时候,总是会出现编译错误。其原因在于通配符所表示的类型是未知的。

    因为对于List<?>中的元素只能用Object来引用,在有些情况下不是很方便。在这些情况下,可以使用上下界来限制未知类型的范围。 如 List<? extends Number>说明List中可能包含的元素类型是Number及其子类。而List<? super Number>则说明List中包含的是Number及其父类。当引入了上界之后,在使用类型的时候就可以使用上界类中定义的方法。

    类型系统

    在Java中,大家比较熟悉的是通过继承机制而产生的类型体系结构。比如String继承自Object。根据Liskov替换原则,子类是可以替换父类的。当需要Object类的引用的时候,如果传入一个String对象是没有任何问题的。但是反过来的话,即用父类的引用替换子类引用的时候,就需要进行强制类型转换。编译器并不能保证运行时刻这种转换一定是合法的。这种自动的子类替换父类的类型转换机制,对于数组也是适用的。 String[]可以替换Object[]。但是泛型的引入,对于这个类型系统产生了一定的影响。正如前面提到的List是不能替换掉List的。

     

    引入泛型之后的类型系统增加了两个维度:一个是类型参数自身的继承体系结构,另外一个是泛型类或接口自身的继承体系结构。第一个指的是对于 List<String>List<Object>这样的情况,类型参数String是继承自Object的。而第二种指的是 List接口继承自Collection接口。对于这个类型系统,有如下的一些规则:

    • 相同类型参数的泛型类的关系取决于泛型类自身的继承体系结构。即List<String>Collection<String> 的子类型,List<String>可以替换Collection<String>。这种情况也适用于带有上下界的类型声明。

    • 当泛型类的类型声明中使用了通配符的时候,其子类型可以在两个维度上分别展开。如对Collection<? extends Number>来说,其子类型可以在Collection这个维度上展开,即List<? extends Number>Set<? extends Number>等;也可以在Number这个层次上展开,即Collection<Double>Collection<Integer>等。如此循环下去,ArrayList<Long>和 HashSet<Double>等也都算是Collection<? extends Number>的子类型。

    • 如果泛型类中包含多个类型参数,则对于每个类型参数分别应用上面的规则。

    展开全文
  • Java高级编程之泛型

    2020-08-18 15:35:22
    所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、 创建对象时)确定(即传入...
  • java 泛型总结

    2016-09-02 14:01:52
    在具体使用时,可以分为泛型接口、泛型类和泛型方法 第一、泛型类public class ... //不在实例化对象的时候去指定类型有一个好处,就是在调用不同方法的时候可以不同类型的参数。 Dog dog = new Dog(); dog.eat
  • 在开发的时候,总能碰到一个方法返回多个值的情形,除了将对象以入参的方式方法内部以外,还可以通过泛型构造元组来实现。 元组类实例 public class Tuple { public static void main(String[] args)...
  • Java复习笔记---泛型

    2020-07-28 10:02:01
    - 泛型通配符 Integer 是 Number的子类,将子类的对象传给形参是父类的方法中,是可以兼容的。但是在泛型中,是否也具有这样的兼容性呢?...我们设定一个形参是父类的方法。即 public void showKeyValue
  • 比如一个方法如果接收List作为形式参数,那么如果尝试将一个List的对象作为实际参数进去,却发现无法通过编译。虽然从直觉上来说,Object是String的父类,这种类型转换应该是合理的。但是实际上这会产生隐含的类型...
  • 当我们调用一个方法的时候,有时候要参数给方法,但是在调用方法之前我们需要对方法的接受参数类型进行确定,这在设计系统时是有局限性的。试想方法在被调用的时候根据传入的参数类型来确定接受类型,这将大大的...
  • 1.可变参数的作用在于让客户端能够将可变数量的参数方法,但这是个技术露底:当调用一个可变参数方法时,会创建一个对象数组Object[]用来存放可变参数;这个数组应该是一个实现细节,他是可见的。因此,当可变...
  • Java泛型类的继承关系

    万次阅读 2016-03-03 11:18:52
    引言类型兼容的对象可以进行赋值,如可将一个 Integer 对象传一个 Object 对象,因为 Object 是 Integer 的基类。Object someObject = new Object(); Integer someInteger = new Integer(10); someObject = some...
  • 要求:获取父类的私有id的属性值(进来的是一个泛型T) 反射流程,是先获取到class对象,然后通过Field来获取对象的属性方法 常用的方法是: getFields 可以获取自身和继承公共的属性 getDeclaredFields 可以...
  • 要求:获取父类的私有id的属性值(进来的是一个泛型T)反射流程,是先获取到class对象,然后通过Field来获取对象的属性方法常用的方法是:getFields 可以获取自身和继承公共的属性getDeclaredFields 可以获取公共和...
  • 泛型常用特点

    千次阅读 2018-05-18 10:10:56
    比如一个方法如果接收List&lt;Object&gt;作为形式参数,那么如果尝试将一个List&lt;String&gt;的对象作为实际参数进去,却发现无法通过编译。虽然从直觉上来说,Object是String的父类,这种类型...
  • ———-三、引用数据类型的自定义复杂对象2 先建立一个Person 3 再建立一个Student继承Person 4 ArrayList al = new ArrayList(); 左边声明本集合是接受Person的,但是右边只了Student, 同时在语法上下面...
  • java c++互arraylist

    2012-02-20 11:57:00
    Java JNI由浅入深(包括:Java和C++互ArrayList泛型对象参数) 2010-11-25 09:571694人阅读评论(1)收藏举报 我们知道Java一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先...
  • Java FAQ

    2016-11-08 21:13:40
    Java 泛型类中方法传一个对象引用的参数,但是该方法的参数为什么不能调用该对象的方法?因为 Java泛型设计跟 C++ 的模版是不一样的。 C++ 的模版的基本思路是在某个模版类型或模版函数被实例化的时候,将实际...
  • 包装类把基本数据类型转换为对象(每个基本类型的数据在java.lang包中都有一个相应的包装类。)2.提供了一系列的实用方法。3.集合不允许存放基本数据类型的数据,存放数字时,要用包装类型。构造方法:1.所有的包装类...

空空如也

空空如也

1 2 3
收藏数 57
精华内容 22
关键字:

java方法传一个泛型对象

java 订阅