มีการอนุมานประเภทอัตโนมัติใน Java หรือไม่?


113

มีautoประเภทตัวแปรใน Java เช่นเดียวกับที่คุณมีใน C ++ หรือไม่?

ตัวอย่าง:

for ( auto var : object_array)
    std::cout << var << std::endl;

for( auto var : object_array)
    var.do_something_that_only_this_particular_obj_can_do();

ฉันรู้ว่ามีการปรับปรุงสำหรับลูปใน Java แต่มีอัตโนมัติหรือไม่ ถ้าไม่มีการแฮ็กเพื่อทำสิ่งนี้หรือไม่? ฉันกำลังอ้างถึงคุณสมบัติใหม่ใน C ++ 11


1
ทุกอย่างยกเว้นประเภทพื้นฐานสามารถกำหนดให้กับตัวแปรประเภทObjectได้ดังนั้นสำหรับการดำเนินการบางอย่างคุณสามารถใช้Objectที่ที่คุณต้องการautoได้
Zyx 2000

1
ไม่มี java ไม่มีตัวแปรดังกล่าว
Aleksei Bulgak

@ Zyx2000: จากนั้นมันจะใช้to_stringฟังก์ชั่นของวัตถุไม่ใช่วัตถุจริงที่เป็นปัญหาใช่หรือไม่?
Games Brainiac

2
@GamesBrainiac: ไม่มันจะใช้เวอร์ชันที่ถูกแทนที่ถ้ามีอยู่
Keppil

2
คำที่คุณกำลังมองหาไม่ใช่ "อัตโนมัติ" แต่เป็น "การอนุมานประเภท" มีคำถามไม่กี่ข้อเกี่ยวกับการอนุมานประเภทใน Java แม้ว่าส่วนใหญ่จะอ้างถึง generics ดังนั้นฉันไม่แน่ใจว่าจะหารายการที่ซ้ำกันได้อย่างไร ...

คำตอบ:


49

ตอบก่อนที่จะแก้ไขคำถาม:

ไม่มีautoประเภทตัวแปรใน Java ลูปเดียวกันสามารถทำได้ดังนี้:

for ( Object var : object_array)
  System.out.println(var);

Java มีตัวแปรโลคัลซึ่งมีขอบเขตอยู่ภายในบล็อกที่กำหนดไว้ คล้ายกับ C และ C ++ แต่ไม่มีคำหลักอัตโนมัติหรือลงทะเบียน อย่างไรก็ตามคอมไพลเลอร์ Java จะไม่อนุญาตให้ใช้ตัวแปรโลคัลที่ไม่ได้เตรียมใช้งานอย่างชัดเจนและจะให้ข้อผิดพลาดในการคอมไพล์ (ซึ่งแตกต่างจาก C และ C ++ ที่โดยปกติคอมไพเลอร์จะให้คำเตือนเท่านั้น) มารยาท: วิกิพีเดีย

ไม่ไม่มีการอนุมานประเภทหลักใน Java เช่น C ++ มีRFEแต่สิ่งนี้ถูกปิดโดย "จะไม่แก้ไข" เหตุผลที่ระบุคือ:

มนุษย์ได้รับประโยชน์จากความซ้ำซ้อนของการประกาศประเภทในสองวิธี อันดับแรกประเภทซ้ำซ้อนทำหน้าที่เป็นเอกสารที่มีค่า - ผู้อ่านไม่จำเป็นต้องค้นหาคำประกาศ getMap () เพื่อค้นหาว่าประเภทใดที่ส่งคืน ประการที่สองความซ้ำซ้อนช่วยให้โปรแกรมเมอร์สามารถประกาศประเภทที่ต้องการได้และด้วยเหตุนี้จึงได้รับประโยชน์จากการตรวจสอบข้ามที่ดำเนินการโดยคอมไพเลอร์


10
@GamesBrainiac ไม่การเรียกเมธอดมักเป็นรูปแบบหลายรูปแบบใน Java อย่างไรก็ตามสิ่งอื่น ๆ อีกมากมาย (เช่นความละเอียดเกินพิกัดหรือการดำเนินการใด ๆ ที่ไม่ได้กำหนดไว้Object) ไม่สามารถทำได้เช่นนี้ นี่ไม่ใช่คำตอบที่ดีจริง ๆ มันเกิดขึ้นเฉพาะกับการทำงานเพราะตัวอย่างในคำถามนั้นอ่อนแอ

10
คำถามนี้เกี่ยวกับการอนุมานประเภทใน C ++ 11 ไม่เกี่ยวกับการใช้งานแบบเก่าautoใน C และก่อน C ++ 11 การแก้ไขของคุณไม่อยู่ในหัวข้อ

4
"นั่นไม่ใช่สิ่งที่ฉันหมายถึงเมื่อคุณพิมพ์ cast ไปยัง Object มันจะให้ Object's to_string" False เท็จแน่นอน 100%
Louis Wasserman

140
"มนุษย์ได้รับประโยชน์จากความซ้ำซ้อน" มันเป็นความจริง. ทุกเช้าฉันตื่นขึ้นมาและคิดว่า "ฉันจะทำให้รหัสซ้ำซ้อนมากขึ้นได้อย่างไร" เพราะประโยชน์.
อาเสนอ

2
ยิ่งไปกว่านั้นคำตอบนี้ล้าสมัยเนื่องจากvarเป็นคีย์เวิร์ดที่สงวนไว้ตั้งแต่ Java 9.
6infinity8

70

อาจเป็น Java 10 ที่มีสิ่งที่คุณ (และฉัน) ต้องการผ่านvarคีย์เวิร์ด

var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>

จากJDK Enhancement Proposals 286


อัปเดต: Yap คุณลักษณะนี้ทำให้เป็นรุ่น Java 10!


6
นี่เป็นการปรับปรุง แต่คำหลักนั้นสามารถใช้ได้กับตัวแปรท้องถิ่นเท่านั้น ไม่ทรงพลังเท่าการอนุมานประเภทอัตโนมัติ C ++
texasbruce

7
Minor nit-pick: varไม่ใช่คีย์เวิร์ด! จากJLS : "var ไม่ใช่คีย์เวิร์ด แต่เป็นตัวระบุที่มีความหมายพิเศษเป็นประเภทของการประกาศตัวแปรโลคัล" ดังนั้นไม่เหมือนกับคำหลักไม่มีอะไรที่จะหยุดคุณเรียกตัวแปรหรือเมธอด "var" ได้
Klitos Kyriacou

2
จุดดี @KlitosKyriacou แต่ถ้าฉันคิดว่าจะแทนที่ 'คำหลัก' ด้วย 'ตัวระบุ' - หรือแม้แต่ 'ตัวระบุที่มีความหมายพิเศษเป็นประเภทของการประกาศตัวแปรท้องถิ่น' - ฉันคิดว่าคำตอบจะไม่ค่อยชัดเจน แต่ใช่varไม่ได้อยู่ในรายการคำหลัก
sorrymissjackson

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

25

Java 7 แนะนำไวยากรณ์เพชร

Box<Integer> integerBox = new Box<>(); // Java 7

เมื่อเทียบกับ java แบบเก่า

Box<Integer> integerBox = new Box<Integer>(); // Before Java 7

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


4
จริง แต่สิ่งที่เขา (และฉัน) กำลังมองหาคือบางสิ่งเช่นauto integerBox = new Box<Integer>();นี้โดยปกติจะใช้เพื่อรับค่าตอบแทนจากฟังก์ชันซึ่งบางครั้งอาจมีความซับซ้อนเช่นHashMap<String, LinkedList<Operation, Set<Integer>>>
Roee Gavirel

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

18

ใน Java 8 คุณสามารถใช้การอนุมานประเภทแลมบ์ดาเพื่อหลีกเลี่ยงการประกาศประเภท อะนาล็อกกับตัวอย่างของผู้ถามคือ:

object_array.forEach(var -> System.out.println(var)); 
object_array.forEach(var -> var.do_something_that_only_this_particular_obj_can_do());

ทั้งสองอย่างนี้สามารถทำให้ง่ายขึ้นโดยใช้การอ้างอิงวิธีการ:

object_array.forEach(System.out::println); 
object_array.forEach(ObjectType::do_something_that_only_this_particular_obj_can_do);

8

ในระยะสั้นไม่มีไม่มีประเภทอัตโนมัติ หากสิ่งที่คุณทำคือการพิมพ์ค่าคุณสามารถอ้างถึงค่าเป็นObjectไฟล์.


หรือการคำนวณhashCodeหรือการรวบรวมชื่อคลาสหรือ ... คุณมีความคิด;) แม้ว่ารายการจะสั้น ดูเอกสารของคลาส Object (ความคิดเห็นสำหรับผู้เริ่มต้นฉันแน่ใจว่าคุณรู้จัก SimonC)
Alexander Malakhov

5

ไม่ใช่โซลูชัน Java ที่บริสุทธิ์อย่างไรก็ตามการเพิ่มไลบรารีที่เรียกว่าlombokจะช่วยให้เวทมนตร์ด้านล่างสามารถรวบรวมและทำงานได้คล้ายกับautoคำหลักใน C ++

List<String> strList = Arrays.asList("foo", "bar", "baz");
for (val s: strList){
    System.out.println(s.length());
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.