สิ่งที่ทำให้ javac ออกคำเตือน“ ใช้การดำเนินการที่ไม่ถูกตรวจสอบหรือไม่ปลอดภัย”


291

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

javac Foo.java
Note: Foo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

ฉันกำลังสร้างบางคลาสที่ใช้แบบไดนามิกsun.misc.Unsafeและมันให้คำแนะนำเหล่านี้ที่ผลลัพธ์
Davut Gürbüz

คำตอบ:


392

สิ่งนี้เกิดขึ้นใน Java 5 และใหม่กว่าหากคุณใช้คอลเล็กชันที่ไม่มีตัวระบุประเภท (เช่นArraylist()แทนArrayList<String>()) ก็หมายความว่าคอมไพเลอร์ไม่สามารถตรวจสอบว่าคุณกำลังใช้คอลเลกชันในทางชนิดปลอดภัยโดยใช้ยาชื่อสามัญ

หากต้องการกำจัดคำเตือนให้ระบุเฉพาะเกี่ยวกับประเภทของวัตถุที่คุณจัดเก็บในคอลเลกชัน ดังนั้นแทนที่จะ

List myList = new ArrayList();

ใช้

List<String> myList = new ArrayList<String>();

ใน Java 7 คุณสามารถร่น instantiation ทั่วไปโดยใช้อนุมานชนิด

List<String> myList = new ArrayList<>();

ใน Java 7 ผมได้เตือนเดียวกันแม้จะใช้ประเภทการรบกวนกับคอลเลกชันนี้:ConcurrentHashMap<Integer, Object> objs = new ConcurrentHashMap()
Lucio

13
@Lucio คุณยังต้องใช้วงเล็บเหลี่ยม new ConcurrentHashMap<>()
Bill the Lizard

3
เพียงเพื่อชี้ให้เห็นว่านี่ไม่ใช่คอลเลกชันที่เฉพาะเจาะจง คุณได้รับข้อผิดพลาดเนื่องจากคอมไพเลอร์ Java ไม่สามารถรับรองความปลอดภัยโดยทั่วไปได้ ตัวอย่างเช่นคำเตือนเดียวกันถูกสร้างขึ้นด้วยรหัสต่อไปนี้: AbstractMap.SimpleEntry <String, String> entry = new AbstractMap.SimpleEntry ("hello", "world");
semonte

1
-Xlint:uncheckedกับMAVEN
vanduc1102

200

หากคุณทำสิ่งที่มันแนะนำและคอมไพล์ใหม่ด้วยสวิตช์ "-Xlint: ไม่ถูกตรวจสอบ" มันจะให้ข้อมูลโดยละเอียดเพิ่มเติมแก่คุณ

เช่นเดียวกับการใช้ประเภท raw (ตามที่อธิบายโดยคำตอบอื่น ๆ ), cast ที่ไม่ถูกตรวจสอบสามารถทำให้เกิดการเตือนได้เช่นกัน

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

@SuppressWarnings("unchecked")
public void myMethod()
{
    //...
}

12
ฉันหวังว่าผู้คนจำนวนมากจะถอนคำตอบนี้ ฉันยืนโดยการเลือกคำตอบ @Bill the Lizard แต่คำตอบนี้อยู่ใกล้กับหัวใจของฉันเพื่อแสดงให้ฉันเห็นว่าคำตอบนั้นจ้องมองที่ฉันถูกต้องในหน้าในการเตือนตัวเองรวมทั้งอธิบายเหตุผลอื่นสำหรับการพบข้อผิดพลาด
แถบเครื่องมือ

1
นี่คือคำตอบที่ดีที่สุด!
russellhoff

คำตอบนี้ควรถูกทำเครื่องหมายว่าเป็นทางออก! ขอบคุณ!
Alexander Malygin

19

สำหรับ Android Studio คุณต้องเพิ่ม:

allprojects {

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs << "-Xlint:unchecked"
        }
    }

    // ...
}

ในไฟล์ build.gradle ของโครงการของคุณเพื่อทราบว่าข้อผิดพลาดนี้เกิดขึ้นที่ใด


ขอบคุณฉันพบว่าคำเตือนของฉันมาจากการเพิ่มสิ่งนี้
JackOuttaBox

ฉันได้รับคำเตือนนี้และ AS จะแสดงคลาสที่ผลิต และนี่ไม่ใช่ข้อผิดพลาดเพียงแค่เตือน ทำไมเราควรเพิ่มตัวเลือกนี้ คลาสปัญหาไม่ปรากฏในสถานการณ์ของคุณใช่ไหม
CoolMind

ฮ่า ๆ ฉันเพิ่งตอบคำถามและไม่ปัญหาจะไม่ปรากฏจนกว่าคุณจะเพิ่ม
Borzh

16

คำเตือนนี้หมายความว่ารหัสของคุณทำงานในประเภท raw ให้คอมไพล์ตัวอย่างใหม่ด้วย

-Xlint:unchecked 

เพื่อรับรายละเอียด

แบบนี้:

javac YourFile.java -Xlint:unchecked

Main.java:7: warning: [unchecked] unchecked cast
        clone.mylist = (ArrayList<String>)this.mylist.clone();
                                                           ^
  required: ArrayList<String>
  found:    Object
1 warning

docs.oracle.com พูดถึงที่นี่: http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html


1
ฉันคิดว่ามันทำ เขาเชื่อมโยงไปยังเอกสารของ Oracle สำหรับคำเตือนที่แน่นอนนี้
Nick Westgate

6

ฉันเรียน 2 ปีและมีชั้นเรียนใหม่ ฉันแก้ไขมันใน Android Studio ดังต่อไปนี้:

allprojects {

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs << "-Xlint:unchecked"
        }
    }

}

ในไฟล์ build.gradle โครงการของฉัน ( โซลูชัน Borzh )

และถ้ามีเหลือ Metheds:

@SuppressWarnings("unchecked")
public void myMethod()
{
    //...
}

5

ตัวอย่างเช่นเมื่อคุณเรียกใช้ฟังก์ชันที่ส่งคืน Generic Collections และคุณไม่ได้ระบุพารามิเตอร์ทั่วไปด้วยตนเอง

สำหรับฟังก์ชั่น

List<String> getNames()


List names = obj.getNames();

จะสร้างข้อผิดพลาดนี้

เพื่อแก้ปัญหาคุณเพียงแค่เพิ่มพารามิเตอร์

List<String> names = obj.getNames();

5

คำเตือน "ไม่ จำกัด หรือดำเนินการที่ไม่ปลอดภัย" ถูกเพิ่มเมื่อจาวาเพิ่มGenericsถ้าฉันจำได้อย่างถูกต้อง มันมักจะขอให้คุณมีความชัดเจนมากขึ้นเกี่ยวกับประเภทในทางใดทางหนึ่ง

ตัวอย่างเช่น. รหัสArrayList foo = new ArrayList();ทริกเกอร์คำเตือนนั้นเพราะ javac กำลังมองหาArrayList<String> foo = new ArrayList<String>();


2

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

นี่เป็นตัวอย่างสั้น ๆ (และค่อนข้างโง่) ที่จะแสดง:

import java.io.Serializable;

public class SimpleGenericClass<T> implements Serializable {

    public Serializable getInstance() {
        return this;
    }

    // @SuppressWarnings("unchecked")
    public static void main() {

        SimpleGenericClass<String> original = new SimpleGenericClass<String>();

        //  java: unchecked cast
        //    required: SimpleGenericClass<java.lang.String>
        //    found:    java.io.Serializable
        SimpleGenericClass<String> returned =
                (SimpleGenericClass<String>) original.getInstance();
    }
}

getInstance () ส่งคืนออบเจ็กต์ที่ใช้ Serializable สิ่งนี้จะต้องถูกส่งไปยังประเภทจริง แต่นี่เป็นนักแสดงที่ไม่ถูกตรวจสอบ


0

การแก้ปัญหาคือการใช้ประเภทเฉพาะใน<>ชอบArrayList<File>เช่น

ตัวอย่าง:

File curfolder = new File( "C:\\Users\\username\\Desktop");
File[] file = curfolder.listFiles();
ArrayList filename = Arrays.asList(file);

โค้ดด้านบนสร้างคำเตือนเพราะArrayListไม่ใช่ประเภทที่เฉพาะเจาะจง

File curfolder = new File( "C:\\Users\\username\\Desktop");
File[] file = curfolder.listFiles();
ArrayList<File> filename = Arrays.asList(file);

รหัสข้างต้นจะทำอะไรได้ดี การเปลี่ยนแปลงจะอยู่ในบรรทัดที่สามหลังจากนั้นArrayListเท่านั้น


0

คุณสามารถเก็บไว้ในรูปแบบทั่วไปและเขียนเป็น:

// list 2 is made generic and can store any type of Object
        ArrayList<Object> list2 = new ArrayList<Object>();

การตั้งค่าชนิดของ ArrayList เป็นวัตถุทำให้เราได้เปรียบในการจัดเก็บข้อมูลประเภทใด ๆ คุณไม่จำเป็นต้องใช้ -Xlint หรืออย่างอื่น


0

คำเตือนนี้อาจถูกยกขึ้นเนื่องจาก

ใหม่ HashMap () หรือใหม่ ArrayList () ที่เป็นประเภททั่วไปจะต้องมีความเฉพาะเจาะจงมิฉะนั้นคอมไพเลอร์จะสร้างคำเตือน

โปรดตรวจสอบให้แน่ใจว่าหากรหัสของคุณมีสิ่งต่อไปนี้คุณต้องเปลี่ยนตาม

ใหม่ HashMap () => แผนที่แผนที่ = ใหม่ HashMap () ใหม่ HashMap () => แผนที่แผนที่ = ใหม่ HashMap <> ()

new ArrayList () => List map = new ArrayList () new ArrayList () => List map = new ArrayList <> ()


0

ArrayList<Map<String, Object>> items = (ArrayList<Map<String, Object>>) value;ฉันมี เนื่องจากvalueเป็นโครงสร้างที่ซับซ้อน (ฉันต้องการทำความสะอาด JSON ) อาจมีการรวมกันของตัวเลขบูลีนสตริงสตริงและอาร์เรย์ ดังนั้นฉันจึงใช้วิธีแก้ปัญหาของ @Dan Dyer:

@SuppressWarnings("unchecked")
ArrayList<Map<String, Object>> items = (ArrayList<Map<String, Object>>) value;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.