Kotlin调用Java方法时,如何转换java.util.ArrayList为kotlin.collections.ArrayList?
解决Kotlin接收Java返回的ArrayList类型问题
别担心,这个问题在Kotlin与Java互操作时非常常见,有几种简单且安全的处理方式,我结合你的代码来一步步说明:
一、最推荐:先修正Java代码的泛型(类型安全优先)
你的Java类LoadAllContacts里的loadContacts()方法返回的是原始类型的ArrayList,这不仅在Kotlin里会触发类型不安全警告,也是导致你类型不匹配的核心原因之一。先给Java代码加上泛型约束:
修改后的Java代码片段:
public class LoadAllContacts { // 修正为带泛型的集合 public static ArrayList<HashMap<String, String>> al = null; public static final String[] keys = {"name", "number"}; // 补充number字段,匹配你Kotlin代码的取值逻辑 public static final int[] ids = {R.id.contact_name, R.id.contact_number}; // 修正方法的返回类型为带泛型的ArrayList public ArrayList<HashMap<String, String>> loadContacts() { al = new ArrayList<HashMap<String, String>>(); try { cursor_Android_Contacts = contentResolver.query( ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC" ); } catch (Exception e) { Log.e("error in contact", e.getMessage()); } if (cursor_Android_Contacts.getCount() > 0) { if (cursor_Android_Contacts.moveToFirst()) { do { // 修正HashMap为带泛型的类型 HashMap<String, String> hm = new HashMap<>(); String contact_id = cursor_Android_Contacts.getString( cursor_Android_Contacts.getColumnIndex(ContactsContract.Contacts._ID) ); String contact_display_name = cursor_Android_Contacts.getString( cursor_Android_Contacts.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME) ); hm.put(keys[0], contact_display_name); int hasPhoneNumber = Integer.parseInt( cursor_Android_Contacts.getString( cursor_Android_Contacts.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER) ) ); if (hasPhoneNumber > 0) { Cursor phoneCursor = contentResolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " =? ", new String[]{contact_id}, null ); if (phoneCursor.moveToFirst()) { String phoneNumber = phoneCursor.getString( phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) ); hm.put(keys[1], phoneNumber); // 存入电话号码,对应Kotlin代码的取值 } phoneCursor.close(); } al.add(hm); } while (cursor_Android_Contacts.moveToNext()); } return al; } return al; } }
二、Kotlin中直接接收(无需额外转换)
在JVM平台上,kotlin.collections.ArrayList本质上就是java.util.ArrayList的类型别名,两者完全兼容。只要Java代码返回的是带泛型的ArrayList<HashMap<String,String>>,你可以直接赋值:
修改后的Kotlin代码片段:
class ContactAllFragment : Fragment() { // 类名首字母大写,符合Kotlin编码规范 @BindView(R.id.contacts_lv) lateinit var contact_lv: ListView var al = ArrayList<HashMap<String,String>>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_contact_all, container, false) ButterKnife.bind(this, view) // 直接接收,无需转换 al = LoadAllContacts(requireContext().contentResolver, requireContext()) .loadContacts() val adapter = SimpleAdapter( context, al, R.layout.listview_style, LoadAllContacts.keys, LoadAllContacts.ids ) contact_lv.adapter = adapter // 修正为赋值adapter属性,原代码的adapter()是错误写法 return view } @OnItemClick(R.id.contacts_lv) fun onItemClick(parent: AdapterView<*>?, position: Int) { // 补全position的类型参数 val hmElement: HashMap<String,String> = al[position] // Kotlin用[]代替get(),更简洁 val name = hmElement[LoadAllContacts.keys[0]] ?: "" // 加上空安全处理,避免空指针 val number = hmElement[LoadAllContacts.keys[1]] ?: "" } }
三、如果暂时不能修改Java代码(兼容原始类型)
如果因为某些原因无法修改Java代码,你可以先做一次安全的类型转换,再转换为Kotlin的ArrayList:
// 先把原始类型的ArrayList转换为带泛型的List,再转为Kotlin ArrayList val javaList = LoadAllContacts(requireContext().contentResolver, requireContext()) .loadContacts() as List<HashMap<String,String>> al = javaList.toCollection(ArrayList())
或者更简洁的写法:
al = (LoadAllContacts(requireContext().contentResolver, requireContext()) .loadContacts() as ArrayList<HashMap<String,String>>)
注意:这种方式存在类型转换风险,如果Java集合里的元素不是
HashMap<String,String>,会抛出ClassCastException,所以还是优先推荐修正Java代码的泛型。
内容的提问来源于stack exchange,提问作者Abhishek Borikar
相关产品推荐
相关产品推荐

