การใช้คำหลักvarใน C # คือการประกาศชนิดโดยนัย ไวยากรณ์เทียบเท่า Java สำหรับvarคืออะไร?
การใช้คำหลักvarใน C # คือการประกาศชนิดโดยนัย ไวยากรณ์เทียบเท่า Java สำหรับvarคืออะไร?
คำตอบ:
ไม่มีเลย อนิจจาคุณต้องพิมพ์ชื่อเต็ม
แก้ไข: 7 ปีหลังจากการโพสต์, การอนุมานประเภทสำหรับตัวแปรท้องถิ่น (กับvar
) ถูกเพิ่มใน Java 10
แก้ไข: 6 ปีหลังจากโพสต์, เพื่อรวบรวมความคิดเห็นจากด้านล่าง:
เหตุผล C # มีvar
คำหลักเนื่องจากเป็นไปได้ที่จะมีประเภทที่ไม่มีชื่อใน. NET เช่น:
var myData = new { a = 1, b = "2" };
myData
ในกรณีนี้มันจะเป็นไปไม่ได้ที่จะให้ชนิดที่เหมาะสมในการ 6 ปีที่แล้วสิ่งนี้เป็นไปไม่ได้ใน Java (ทุกประเภทมีชื่อแม้ว่าพวกเขาจะ verbose อย่างมากและไม่สวย) ฉันไม่ทราบว่าสิ่งนี้มีการเปลี่ยนแปลงในเวลาเฉลี่ย
var
dynamic
ไม่ได้เป็นเช่นเดียวกับ var
iables ยังคงพิมพ์แบบคงที่ 100% สิ่งนี้จะไม่รวบรวม:
var myString = "foo";
myString = 3;
var
ก็มีประโยชน์เมื่อประเภทนั้นชัดเจนจากบริบท ตัวอย่างเช่น:
var currentUser = User.GetCurrent();
ฉันสามารถพูดได้ว่าในรหัสใด ๆ ที่ฉันรับผิดชอบcurrentUser
มีUser
หรือได้รับในชั้นเรียน เห็นได้ชัดว่าหากการใช้งานของคุณUser.GetCurrent
คืนค่าเป็น int อาจเป็นอันตรายกับคุณ
สิ่งนี้ไม่มีส่วนเกี่ยวข้องvar
แต่ถ้าคุณมีลำดับชั้นการสืบทอดแปลก ๆ ที่คุณเงาวิธีการด้วยวิธีอื่น ๆ (เช่นnew public void DoAThing()
) อย่าลืมว่าวิธีการที่ไม่ใช่แบบเสมือนได้รับผลกระทบจากประเภทที่พวกมันถูกโยนเป็น
ฉันไม่สามารถจินตนาการถึงสถานการณ์ในโลกแห่งความจริงที่สิ่งนี้บ่งบอกถึงการออกแบบที่ดี แต่สิ่งนี้อาจไม่ทำงานอย่างที่คุณคาดไว้:
class Foo {
public void Non() {}
public virtual void Virt() {}
}
class Bar : Foo {
public new void Non() {}
public override void Virt() {}
}
class Baz {
public static Foo GetFoo() {
return new Bar();
}
}
var foo = Baz.GetFoo();
foo.Non(); // <- Foo.Non, not Bar.Non
foo.Virt(); // <- Bar.Virt
var bar = (Bar)foo;
bar.Non(); // <- Bar.Non, not Foo.Non
bar.Virt(); // <- Still Bar.Virt
ตามที่ระบุไว้วิธีการเสมือนจะไม่ได้รับผลกระทบจากสิ่งนี้
ไม่ไม่มีวิธีที่ไม่ซุ่มซ่ามในการเริ่มต้นvar
โดยไม่มีตัวแปรจริง
var foo1 = "bar"; //good
var foo2; //bad, what type?
var foo3 = null; //bad, null doesn't have a type
var foo4 = default(var); //what?
var foo5 = (object)null; //legal, but go home, you're drunk
ในกรณีนี้เพียงทำแบบเก่า:
object foo6;
var p = new X(); p.Z()
ไม่เหมือนกับSuperX p = new X(); p.Z()
X และและ SuperX X : SuperX
ทั้งหมด ด้วยคงที่ประเภทของการอยู่เสมอในตัวอย่างแรกข้างต้น แต่เสมอในตัวอย่างที่สอง ความแตกต่างที่ลึกซึ้ง แต่สำคัญที่ต้องระวัง แต่คำตอบของคุณถูกต้องมาก :-)var
p
X
SuperX
var
ไม่ทำให้รหัสชัดเจนน้อยลง ค่อนข้างตรงกันข้ามในความคิดของฉัน ทำไมตัวอย่างเช่นเขียนประเภทสอง (หรือสามครั้ง) ในแถวเดียวกันเมื่อคุณประกาศและยกตัวอย่าง ( RadioButton radioButton = new RadioButton();
) var
ทำให้คุณค่อนข้างคิดว่าสองครั้งเมื่อคุณตั้งชื่อตัวแปรของคุณเพราะมันจะมุ่งเน้นไปที่การทำงานมากกว่าประเภท (เช่น UserCollection collection = new userRepository.GetUsers();
ค่อนข้างจะกลายเป็นธรรมชาติมากกว่าvar users = userRepository.GetUsers();
) หากคุณคิดว่าvar
ไม่ชัดเจนอาจเป็นเพราะไม่ได้ใช้งาน
var
แน่นอนมากสามารถทำให้การใช้รหัสชัดเจนดี แต่ก็สามารถทำให้มันชัดเจนเกินไปใช้ไม่ดี; ชอบตัวเลือกการจัดรูปแบบมากมาย ยอดคงเหลือแตกต่างกันไปขึ้นอยู่กับว่าคุณใช้วัตถุและข้อมูลทั่วไปโดยไม่ระบุชื่อซึ่งไม่มีอยู่ใน. NET 1.0 ทำให้มีประโยชน์น้อยกว่าในฐานะคำหลักสมมุติในรุ่นแรกของC♯ ฉันเพียงจะชื่อRadioButton
radioButton
ในกรณีของโรงงานหรือผู้ช่วยวิธีการที่มีเพียงสิ่งเดียวที่สำคัญเกี่ยวกับปุ่มก็คือว่ามันเป็นอย่างอื่นที่บ้าของมีหรือไม่มีRadioButton
var
var
คุณถ้าไม่มาก แต่ฉันได้เปลี่ยนความคิดเห็นของฉันและบางทีมันอาจจะง่ายเหมือนคำถามของความคิดเห็นที่แตกต่างกันเพราะฉันยังคิดว่าคุณผิดเมื่อคุณพูดว่ามันเป็น ไม่ว่าคุณจะใช้วัตถุและชื่อสามัญมากน้อยเพียงใด) การประกาศประเภทมักจะเป็นเพียงแค่รหัสเสียงถ้าคุณไม่สามารถเข้าใจรหัสได้หากไม่มีรหัสก็อาจไม่ชัดเจนในทั้งสองกรณี
var
ตัวมันเองก็ขอให้คอมไพเลอร์สรุปประเภทจากการมอบหมาย; มันเป็นน้ำตาลทราย ตอนแรกฉันไม่เชื่อ แต่ฉันใช้มันอย่างเคร่งศาสนาและยังไม่เคยเจอเวลาที่มันทำให้เกิดความสับสน มันลบความซ้ำซ้อนเมื่อ instantiating และลบความจำเป็นในการตรวจสอบประเภทเมื่อมีการอ้างอิง ไม่มีเทียบเท่า JAVA ณ JAVA 9
หากคุณเพิ่มลอมบอกในโครงการของคุณคุณสามารถใช้คำหลักวาล
final
ไม่จำเป็นต้องเปลี่ยนแปลง พิจารณาfinal StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
var
เช่นกัน projectlombok.org/features/experimental/var.html
JEP - ข้อเสนอการปรับปรุง JDK
http://openjdk.java.net/jeps/286
JEP 286: การอนุมานประเภทตัวแปรท้องถิ่น
ผู้แต่ง Brian Goetz
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
ฉันได้ปรุงปลั๊กอินสำหรับ IntelliJ แล้ว - ในแบบที่ให้คุณกับvar
Java มันสับดังนั้นการสละสิทธิ์ตามปกติใช้ แต่ถ้าคุณใช้ IntelliJ สำหรับการพัฒนา Java ของคุณและต้องการที่จะลองมันออกมามันจะอยู่ที่https://bitbucket.org/balpha/varsity
ด้วยการเปิดตัวของ JDK 10 เมื่อวันที่ 20 มีนาคม, Java ตอนนี้มีvar
ชื่อประเภทที่สงวนไว้ (ไม่ได้เป็นคำหลักดูด้านล่าง) ตามที่ระบุในJEP 286 สำหรับตัวแปรโลคัลตอนนี้สิ่งต่อไปนี้ใช้ได้ใน Java 10 หรือสูงกว่า:
var map = new HashMap<String, Integer>();
var
ชื่อประเภทที่สงวนไว้ใน Java เป็นเกือบจะเหมือนกับvar
คำหลักใน C # ในการที่ทั้งสองช่วยให้สำหรับการพิมพ์โดยปริยาย (ดูด้านล่างสำหรับความแตกต่างที่สำคัญ) var
ใน Java สามารถใช้สำหรับการอนุมานประเภทโดยนัยในบริบทต่อไปนี้ (ตามที่ระบุในJEP 286: เป้าหมาย ):
ดังนั้นจึงvar
ไม่สามารถใช้สำหรับฟิลด์ประเภทส่งคืนชื่อคลาสหรือชื่ออินเทอร์เฟซ เหตุผลของมันคือการลบความจำเป็นในการรวมชื่อชนิดยาวเมื่อประกาศและกำหนดตัวแปรท้องถิ่นตามที่ระบุในJEP 286 (เขียนโดย Brian Goetz):
เราพยายามปรับปรุงประสบการณ์ของนักพัฒนาโดยลดพิธีที่เกี่ยวข้องกับการเขียนโค้ด Java ในขณะที่รักษาความมุ่งมั่นของจาวาในการรักษาความปลอดภัยของสแตติกชนิดต่างๆ
var
การกำหนดขอบเขตใน Javaควรสังเกตว่าvar
ไม่ใช่คำหลักใน Java แต่เป็นชื่อประเภทที่สงวนไว้ ตามที่ยกมาจาก JEP 286:
var ตัวระบุไม่ใช่คำหลัก แต่เป็นชื่อประเภทที่สงวนไว้ ซึ่งหมายความว่ารหัสที่ใช้ var เป็นตัวแปรวิธีการหรือชื่อแพคเกจจะไม่ได้รับผลกระทบ รหัสที่ใช้ var เป็นคลาสหรือชื่ออินเทอร์เฟซจะได้รับผลกระทบ (แต่ชื่อเหล่านี้หายากในทางปฏิบัติเนื่องจากละเมิดหลักการตั้งชื่อตามปกติ)
โปรดทราบว่าเนื่องจากvar
เป็นชื่อประเภทที่สงวนไว้และไม่ใช่คำหลักจึงยังสามารถใช้สำหรับชื่อแพคเกจชื่อเมธอดและชื่อตัวแปร (พร้อมกับบทบาทการรบกวนประเภทใหม่) ตัวอย่างเช่นต่อไปนี้เป็นตัวอย่างทั้งหมดของการใช้งานที่ถูกต้องของvar
ใน Java:
var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;
ตามที่ยกมาจาก JEP 286:
การรักษานี้จะถูก จำกัด ให้กับตัวแปรในท้องถิ่นที่มี initializers ดัชนีในการปรับปรุงสำหรับวงและท้องถิ่นที่ประกาศในแบบดั้งเดิมสำหรับวง; มันจะไม่สามารถใช้ได้สำหรับ formals วิธี formals นวกรรมิกชนิดกลับวิธีการเขตข้อมูลจับ formals หรือการประกาศตัวแปรชนิดอื่น ๆ
var
ใน Java & Cนี่คือความแตกต่างที่น่าสังเกตระหว่างvar
ใน C # และ Java รวมถึงต่อไปนี้: var
สามารถใช้เป็นชื่อประเภทใน C # แต่ไม่สามารถใช้เป็นชื่อคลาสหรือชื่ออินเตอร์เฟสใน Java ตามเอกสาร C # (ตัวแปรท้องถิ่นที่พิมพ์โดยนัย) :
หากประเภทที่มีชื่อ
var
อยู่ในขอบเขตvar
คำหลักจะแก้ไขเป็นชื่อประเภทนั้นและจะไม่ถือว่าเป็นส่วนหนึ่งของการประกาศตัวแปรท้องถิ่นที่พิมพ์โดยนัย
ความสามารถในการใช้var
เป็นชื่อประเภทใน C # สร้างความซับซ้อนและแนะนำกฎการแก้ปัญหาที่ซับซ้อนซึ่งถูกหลีกเลี่ยงโดยvar
ใน Java โดยไม่อนุญาตให้var
ใช้เป็นคลาสหรือชื่ออินเตอร์เฟส สำหรับข้อมูลเกี่ยวกับความซับซ้อนของvar
ชื่อประเภทใน C #, ดูข้อ จำกัด นำไปใช้โดยปริยายพิมพ์ประกาศตัวแปร สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเหตุผลที่อยู่เบื้องหลังการตัดสินใจกำหนดขอบเขตสำหรับ `var ใน Java ดูJEP 286: กำหนดขอบเขตทางเลือก
var
สำหรับฟิลด์หรือชนิดส่งคืนได้? เหตุใดจึงสำคัญที่ควรทราบ
var
ใน Java ไม่สามารถใช้สำหรับฟิลด์หรือประเภทส่งคืน สิ่งนี้มีความสำคัญเนื่องจากข้อ จำกัด นี้ทำให้var
บริบทอ่อนไหวซึ่งสามารถใช้ได้ในบริบทบางอย่างเท่านั้น (ตัวแปรท้องถิ่น) และอื่น ๆ สิ่งนี้ไม่จำเป็นต้องเป็นข้อแตกต่างระหว่าง Java และ C # ที่ควรจดบันทึก แต่ข้อ จำกัด ที่สำคัญโดยทั่วไปเมื่อใช้var
ใน Java
var
ชื่อชั้นเรียนและใช้เป็นเช่นนี้ ในทางเทคนิคแล้วมันเป็น "คำหลักบริบท" ในกรณีของ c # แต่ใน Java ดูเหมือนว่าคุณไม่สามารถทำเช่นเดียวกัน ช่วยแก้ให้ด้วยนะถ้าฉันผิด.
var
เป็นชื่อคลาสหรือชื่ออินเทอร์เฟซใน Java (ซึ่งไม่ใช่เรื่องธรรมดาอยู่แล้ว) แต่คุณสามารถใช้เป็นชื่อตัวแปรชื่อเมธอดและชื่อแพ็คเกจได้ ยกตัวอย่างเช่นvar var = 1;
เป็นคำสั่งที่ถูกต้อง Java แต่พยายามที่จะประกาศในชั้นเรียนเป็นผลในข้อผิดพลาด:public class var {}
as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations
ฉันได้อัปเดตคำตอบข้างต้นเพื่อดูรายละเอียดเพิ่มเติมเกี่ยวกับเหตุผลเบื้องหลังvar
ใน Java และความแตกต่างกับvar
ใน C #
มันจะได้รับการสนับสนุนใน JDK 10 มันยังเป็นไปได้ที่จะเห็นมันในการดำเนินการในการสร้างการเข้าถึงก่อน
JEP 286 :
เพิ่มประสิทธิภาพภาษา Java เพื่อขยายการอนุมานประเภทเพื่อประกาศตัวแปรท้องถิ่นด้วย initializers
ดังนั้นตอนนี้แทนที่จะเขียน:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
ที่คุณเขียน:
var list = new ArrayList<String>();
var stream = myStream();
หมายเหตุ:
var
เป็นชื่อประเภทที่สงวนไว้หากคุณต้องการทดลองใช้งานโดยไม่ต้องติดตั้ง Java ในระบบท้องถิ่นของคุณฉันสร้างอิมเมจ Docker ที่มี JDK 10 ติดตั้งไว้:
$ docker run -it marounbassam/ubuntu-java10 bash
root@299d86f1c39a:/# jdk-10/bin/jshell
Mar 30, 2018 9:07:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
| Welcome to JShell -- Version 10
| For an introduction type: /help intro
jshell> var list = new ArrayList<String>();
list ==> []
var
) จะไม่เทียบเท่า ในvar
ตัวอย่างlist
เป็นประเภทไม่ได้ArrayList
List
วิธีแก้ปัญหาอย่างง่าย (สมมติว่าคุณกำลังใช้ IDE ที่เหมาะสม) เพียงพิมพ์ 'int' ทุกที่จากนั้นให้กำหนดประเภทให้คุณ
ฉันเพิ่งเพิ่มคลาสที่เรียกว่า 'var' ดังนั้นฉันจึงไม่ต้องพิมพ์อะไรที่แตกต่างออกไป
รหัสนี้ยังละเอียดเกินไป แต่อย่างน้อยคุณก็ไม่จำเป็นต้องพิมพ์มัน!
int
) - ฉันขาดอะไรไปหรือเปล่า? (*: ในขณะที่ฉันจะไม่เรียก Eclipse ว่าเป็น IDE ที่ดี แต่ฉันไม่สามารถตัดสินผู้อื่นได้ ... )
Java 10 ได้รับการอนุมานประเภทตัวแปรท้องถิ่นดังนั้นตอนนี้ก็มีvar
ซึ่งเทียบเท่ากับ C # หนึ่ง (เท่าที่ฉันรู้)
นอกจากนี้ยังสามารถสรุปประเภทที่ไม่ใช่ denotable (ประเภทที่ไม่สามารถมีชื่ออยู่ในสถานที่ที่โดยโปรแกรมเมอร์แม้ว่าซึ่งประเภทนี้ไม่ denotable ที่แตกต่างกัน) ดูเช่นเทคนิคกับvar
และการเรียนที่ไม่ระบุชื่อ (ที่คุณไม่ควรใช้ในที่ทำงาน)
ข้อแตกต่างอย่างหนึ่งที่ฉันพบคือใน C #
ใน Java 10 var
ไม่ใช่ชื่อประเภทที่ถูกกฎหมาย
ในฐานะของ Java ที่ 10 เทียบเท่าคือ var
...
ฉันรู้ว่านี่เก่ากว่า แต่ทำไมไม่สร้างคลาส var และสร้าง constructor ที่มีประเภทต่าง ๆ และขึ้นอยู่กับว่า constructor ใดที่ถูกเรียกใช้คุณจะได้รับ var ที่มีประเภทแตกต่างกัน คุณสามารถสร้างวิธีการในการแปลงประเภทหนึ่งเป็นประเภทอื่น
Lombok
รองรับ varแต่ยังคงจัดเป็นประเภททดลอง:
import lombok.experimental.var;
var number = 1; // Inferred type: int
number = 2; // Legal reassign since var is not final
number = "Hi"; // Compilation error since a string cannot be assigned to an int variable
System.out.println(number);
นี่IntelliJ IDEA
คืออันตรายที่ควรหลีกเลี่ยงเมื่อพยายามที่จะใช้ใน ดูเหมือนว่าจะทำงานได้ตามที่คาดไว้รวมถึงการทำให้สมบูรณ์อัตโนมัติและทุกอย่าง จนกว่าจะมีวิธีแก้ปัญหา "ไม่แฮ็ก" (เช่นเนื่องจากJEP 286: การอนุมานประเภทตัวแปรท้องถิ่น ) นี่อาจเป็นทางออกที่ดีที่สุดของคุณในตอนนี้
ทราบว่าval
ได้รับการสนับสนุนโดยการเป็นอย่างดีโดยไม่ต้องแก้ไขหรือการสร้างLombok
lombok.config
คุณสามารถใน Java 10 แต่สำหรับตัวแปรLocalหมายถึง
คุณสามารถ,
var anum = 10; var aString = "Var";
แต่ไม่สามารถ
var anull = null; // Since the type can't be inferred in this case
ตรวจสอบข้อมูลจำเพาะสำหรับข้อมูลเพิ่มเติม
var
สามารถใช้สำหรับประเภทที่ไม่สามารถปฏิเสธได้หลายรูปแบบรวมถึงประเภทการจับภาพประเภทการแยกและประเภทคลาสที่ไม่ระบุชื่อ และสำหรับ Java 11 นั้นยังสามารถใช้กับพารามิเตอร์แลมบ์ดาได้
โดยทั่วไปคุณสามารถใช้คลาส Object สำหรับประเภทใดก็ได้ แต่คุณต้องทำการแคสต์ชนิดในภายหลัง!
เช่น:-
Object object = 12;
Object object1 = "Aditya";
Object object2 = 12.12;
System.out.println(Integer.parseInt(object.toString()) + 2);
System.out.println(object1.toString() + " Kumar");
System.out.println(Double.parseDouble(object2.toString()) + 2.12);
var
คำที่เป็นทางการในภาษานี้คำตอบของคุณยังหมายถึงวิธีที่ล้าสมัยในขณะนี้
ตอนนี้ฟีเจอร์นี้มีให้ใน Java SE 10 แล้ว var แบบเซฟตี้ได้ทำให้เป็นโลกของ java ในที่สุด :)
แหล่งที่มา: https://www.oracle.com/corporate/pressrelease/Java-10-032018.html
val
(หรือvar
) ถ้าคุณใช้ภาษา "การแทนที่ Java" โดยเฉพาะ ;-)