ฉันจะทราบได้อย่างไรว่าวัตถุแต่ละประเภทอยู่ใน ArrayList <Object>


87

ฉันมี ArrayList ซึ่งประกอบด้วยองค์ประกอบต่าง ๆ ที่นำเข้าจากฐานข้อมูลซึ่งประกอบด้วยสตริงตัวเลขคู่และ ints มีวิธีใช้เทคนิคประเภทการสะท้อนเพื่อค้นหาว่าข้อมูลแต่ละประเภทแต่ละองค์ประกอบเก็บข้อมูลอะไรบ้าง?

FYI: สาเหตุที่มีข้อมูลหลายประเภทเนื่องจากเป็นส่วนหนึ่งของโค้ดจาวาที่เขียนขึ้นเพื่อนำไปใช้กับฐานข้อมูลที่แตกต่างกัน

คำตอบ:


100

ใน C #:
แก้ไขโดยคำแนะนำจากMike

ArrayList list = ...;
// List<object> list = ...;
foreach (object o in list) {
    if (o is int) {
        HandleInt((int)o);
    }
    else if (o is string) {
        HandleString((string)o);
    }
    ...
}

ใน Java:

ArrayList<Object> list = ...;
for (Object o : list) {
    if (o instanceof Integer)) {
        handleInt((Integer o).intValue());
    }
    else if (o instanceof String)) {
        handleString((String)o);
    }
    ...
}

3
จริงๆแล้วแทนที่จะใช้ o.GetType () == typeof (int)) เพียงแค่พูดว่า (o เป็น int);
Michael Brown

1
และถ้าคุณกังวลเกี่ยวกับทุก ๆ นาโนวินาที "as" จะช่วยให้คุณประหยัดได้เพียงเล็กน้อยเมื่อเทียบกับ "เป็น" ด้วยการโยน
Neil

47
คุณไม่สามารถทำinstanceofในกรณี java ได้หรือไม่?
Razor Storm

2
สำหรับกรณี Integer ควรเป็น Integer.class ด้วยฉันเพิ่งลอง Integer.TYPE ไม่ทำงาน
อลันทัวริง

(int) oไม่ทำงานใน Java Cannot cast from Object to intมันก่อให้เกิดข้อผิดพลาด ใช้(Integer o).intValue()แทน
สูงสุด

54

คุณสามารถใช้getClass()วิธีการนี้หรือคุณสามารถใช้ instanceof ตัวอย่างเช่น

for (Object obj : list) {
  if (obj instanceof String) {
   ...
  }
}

หรือ

for (Object obj : list) {
 if (obj.getClass().equals(String.class)) {
   ...
 }
}

โปรดทราบว่าอินสแตนซ์ของจะตรงกับคลาสย่อย ตัวอย่างเช่น of Cเป็นคลาสย่อยของAดังนั้นสิ่งต่อไปนี้จะเป็นจริง:

C c = new C();
assert c instanceof A;

อย่างไรก็ตามสิ่งต่อไปนี้จะเป็นเท็จ:

C c = new C();
assert !c.getClass().equals(A.class)

45
for (Object object : list) {
    System.out.println(object.getClass().getName());
}

7
อย่าลืมเกี่ยวกับค่าว่างถ้าเป็นไปได้ในรายการของคุณ คุณจะได้รับ NullPointerExceptions จากตัวอย่างนี้ด้วยค่า null
John Gardner

13

คุณแทบไม่ต้องการให้คุณใช้สิ่งที่ต้องการ:

Object o = ...
if (o.getClass().equals(Foo.class)) {
    ...
}

เนื่องจากคุณไม่ได้บัญชีสำหรับคลาสย่อยที่เป็นไปได้ คุณต้องการใช้ Class # isAssignableFrom:

Object o = ...
if (Foo.class.isAssignableFrom(o)) {
    ...
}

5

ใน Java เพียงแค่ใช้ตัวดำเนินการ instanceof สิ่งนี้จะดูแลคลาสย่อยด้วย

ArrayList<Object> listOfObjects = new ArrayList<Object>();
for(Object obj: listOfObjects){
   if(obj instanceof String){
   }else if(obj instanceof Integer){
   }etc...
}

5
import java.util.ArrayList;

/**
 * @author potter
 *
 */
public class storeAny {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ArrayList<Object> anyTy=new ArrayList<Object>();
        anyTy.add(new Integer(1));
        anyTy.add(new String("Jesus"));
        anyTy.add(new Double(12.88));
        anyTy.add(new Double(12.89));
        anyTy.add(new Double(12.84));
        anyTy.add(new Double(12.82));

        for (Object o : anyTy) {
            if(o instanceof String){
                System.out.println(o.toString());
            } else if(o instanceof Integer) {
                System.out.println(o.toString());   
            } else if(o instanceof Double) {
                System.out.println(o.toString());
            }
        }
    }
}


3

อินสแตนซ์ของใช้งานได้หากคุณไม่ได้ขึ้นอยู่กับคลาสที่เฉพาะเจาะจง แต่โปรดทราบว่าคุณสามารถมีค่าว่างในรายการได้ดังนั้น obj.getClass () จะล้มเหลว แต่อินสแตนซ์ของจะแสดงผลเท็จเป็นค่าว่างเสมอ


3

ตั้งแต่ Java 8


        mixedArrayList.forEach((o) -> {
            String type = o.getClass().getSimpleName();
            switch (type) {
                case "String":
                    // treat as a String
                    break;
                case "Integer":
                    // treat as an int
                    break;
                case "Double":
                    // treat as a double
                    break;
                ...
                default:
                    // whatever
            }
        });


2

แทนที่จะใช้object.getClass().getName()คุณสามารถใช้ได้object.getClass().getSimpleName()เพราะส่งคืนชื่อคลาสธรรมดาโดยไม่มีชื่อแพ็กเกจรวมอยู่ด้วย

ตัวอย่างเช่น

Object[] intArray = { 1 }; 

for (Object object : intArray) { 
    System.out.println(object.getClass().getName());
    System.out.println(object.getClass().getSimpleName());
}

ให้

java.lang.Integer
Integer

0

คุณบอกว่า "นี่คือโค้ดจาวาที่เขียน" ซึ่งผมอนุมานได้ว่ายังมีโอกาสที่คุณจะออกแบบมันในแบบอื่นได้

การมี ArrayList ก็เหมือนกับการมีของสะสม แทนที่จะบังคับให้อินสแตนซ์ของหรือ getClass ทุกครั้งที่คุณนำอ็อบเจ็กต์ออกจากรายการทำไมไม่ออกแบบระบบเพื่อให้คุณได้รับประเภทของอ็อบเจ็กต์เมื่อคุณดึงข้อมูลจากฐานข้อมูลและเก็บไว้ในคอลเลกชันของประเภทที่เหมาะสมของ วัตถุ?

หรือคุณสามารถใช้หนึ่งในไลบรารีการเข้าถึงข้อมูลจำนวนมากที่มีอยู่เพื่อทำสิ่งนี้ให้กับคุณ


0

หากคุณคาดว่าข้อมูลจะเป็นตัวเลขในรูปแบบใดรูปแบบหนึ่งและสิ่งที่คุณสนใจที่จะทำคือการแปลงผลลัพธ์เป็นค่าตัวเลขฉันขอแนะนำ:

for (Object o:list) {
  Double.parseDouble(o.toString);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.