Một cách sử dụng từ khóa var trong C # là khai báo kiểu ẩn. Cú pháp tương đương Java cho var là gì?
Một cách sử dụng từ khóa var trong C # là khai báo kiểu ẩn. Cú pháp tương đương Java cho var là gì?
Câu trả lời:
Chẳng có ai. Than ôi, bạn phải gõ tên đầy đủ.
Chỉnh sửa: 7 năm sau khi được đăng, nhập suy luận cho các biến cục bộ (với var) đã được thêm vào trong Java 10.
Chỉnh sửa: 6 năm sau khi được đăng, để thu thập một số ý kiến từ bên dưới:
Lý do C # có vartừ khóa là vì có thể có các Loại không có tên trong .NET. Ví dụ:
var myData = new { a = 1, b = "2" };
Trong trường hợp này, không thể đưa ra một loại thích hợp myData. 6 năm trước, điều này là không thể trong Java (tất cả các loại đều có tên, ngay cả khi chúng cực kỳ dài dòng và không thông minh). Tôi không biết nếu điều này đã thay đổi trong thời gian trung bình.
varkhông giống như dynamic. variables vẫn được gõ tĩnh 100%. Điều này sẽ không biên dịch:
var myString = "foo";
myString = 3;varcũng hữu ích khi loại rõ ràng từ bối cảnh. Ví dụ:
var currentUser = User.GetCurrent();
Tôi có thể nói rằng trong bất kỳ mã nào mà tôi chịu trách nhiệm, currentUserđều có một Userlớp hoặc dẫn xuất trong đó. Rõ ràng, nếu bạn thực hiện User.GetCurrenttrả lại một int, thì có lẽ đây là một bất lợi cho bạn.
Điều này không có gì để làm var, nhưng nếu bạn có hệ thống phân cấp thừa kế kỳ lạ nơi bạn che giấu các phương thức với các phương thức khác (ví dụ new public void DoAThing()), đừng quên rằng các phương thức không ảo bị ảnh hưởng bởi Loại mà chúng được sử dụng.
Tôi không thể tưởng tượng một kịch bản trong thế giới thực, nơi đây là biểu hiện của thiết kế tốt, nhưng điều này có thể không hoạt động như bạn mong đợi:
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
Như đã chỉ ra, các phương thức ảo không bị ảnh hưởng bởi điều này.
Không, không có cách nào không vụng về để khởi tạo varmà không có biến thực.
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
Trong trường hợp này, chỉ cần làm theo cách cũ:
object foo6;var p = new X(); p.Z()không giống SuperX p = new X(); p.Z()với tất cả X và SuperX, mặc dù vậy X : SuperX. Với varcác tĩnh loại pluôn luôn là Xtrong ví dụ đầu tiên ở trên, nhưng luôn luôn SuperXtrong ví dụ thứ hai. Một sự khác biệt tinh tế nhưng quan trọng cần phải nhận thức. Nhưng câu trả lời của bạn rất chính xác :-)
varkhông làm cho mã ít rõ ràng hơn. Thay vào đó là ý kiến ngược lại. Tại sao ví dụ viết loại hai (hoặc thậm chí ba) lần trên cùng một hàng khi bạn khai báo và khởi tạo nó ( RadioButton radioButton = new RadioButton();)? varlàm cho bạn thay vì suy nghĩ hai lần khi bạn đặt tên cho các biến của mình bởi vì nó chuyển trọng tâm vào chức năng hơn là loại (ví dụ UserCollection collection = new userRepository.GetUsers();thay vì tự nhiên chuyển thành var users = userRepository.GetUsers();). Nếu bạn nghĩ varlà không rõ ràng thì đó chỉ là vì không sử dụng nó.
varrất chắc chắn có thể làm cho mã rõ ràng được sử dụng tốt, nhưng nó cũng có thể làm cho nó không rõ ràng được sử dụng quá tệ; giống như nhiều tùy chọn định dạng. Số dư khác nhau tùy thuộc vào mức độ bạn sử dụng các đối tượng và tổng quát ẩn danh, không có đối tượng nào tồn tại trong .NET 1.0, khiến nó không hữu dụng như một từ khóa giả định trong phiên bản đầu tiên của C♯. Tôi sẽ chỉ đặt tên cho một RadioButton radioButtontrường hợp của một phương thức của nhà máy hoặc người trợ giúp trong đó điều duy nhất có ý nghĩa về nút đó là nó RadioButton, nếu không thì đó là sự điên rồ có hoặc không có var.
varnhư bạn, nếu không hơn, nhưng tôi đã thay đổi ý kiến của mình, và có lẽ nó đơn giản như một câu hỏi về những ý kiến khác nhau, bởi vì tôi vẫn nghĩ bạn sai khi bạn nói đó là một cho dù bạn đang sử dụng các đối tượng ẩn danh và tổng quát bao nhiêu;) Khai báo kiểu thường chỉ là nhiễu mã, nếu bạn không thể hiểu mã mà không có mã thì có thể không rõ ràng trong cả hai trường hợp.
varchính nó chỉ đơn giản yêu cầu trình biên dịch suy ra kiểu từ bài tập; đó là cú pháp đường. Tôi đã hoài nghi về nó lúc đầu, nhưng tôi sử dụng nó một cách tôn giáo và chưa gặp phải một thời gian mà nó gây ra sự nhầm lẫn. Nó loại bỏ sự dư thừa khi khởi tạo và loại bỏ sự cần thiết phải kiểm tra loại khi tham chiếu. Không có JAVA tương đương với JAVA 9.
Nếu bạn thêm Lombok vào dự án của mình, bạn có thể sử dụng val của nó từ khóa .
finalkhông nhất thiết là bất biến. Hãy xem xétfinal StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
var. projectlombok.org/features/experimental/var.html
JEP - Đề xuất cải tiến JDK
http://openjdk.java.net/jeps/286
JEP 286: Suy luận kiểu biến cục bộ
Tác giả Brian Goetz
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
Tôi đã tạo ra một plugin cho IntelliJ - theo một cách nào đó - cung cấp cho bạn vartrong Java. Đó là một hack, vì vậy các khuyến cáo từ chối thông thường được áp dụng, nhưng nếu bạn sử dụng IntelliJ để phát triển Java và muốn dùng thử, thì đó là tại https://bitbucket.org/balpha/varsity .
Với việc phát hành JDK 10 vào ngày 20 tháng 3, Java hiện bao gồm một vartên loại dành riêng (không phải là từ khóa mà xem bên dưới) như được chỉ định trong JEP 286 . Đối với các biến cục bộ, các biến sau đây hiện hợp lệ trong Java 10 trở lên:
var map = new HashMap<String, Integer>();
Tên varloại dành riêng trong Java gần giống với vartừ khóa trong C #, cả hai đều cho phép nhập ngầm (xem bên dưới để biết những khác biệt quan trọng). vartrong Java chỉ có thể được sử dụng cho suy luận kiểu ngầm định trong các ngữ cảnh sau (như được liệt kê trong JEP 286: Mục tiêu ):
Do đó, var không thể được sử dụng cho các trường, kiểu trả về, tên lớp hoặc tên giao diện. Cơ sở lý luận của nó là loại bỏ sự cần thiết phải bao gồm các tên loại dài khi khai báo và xác định các biến cục bộ, như đã nêu trong JEP 286 (tác giả Brian Goetz):
Chúng tôi tìm cách cải thiện trải nghiệm của nhà phát triển bằng cách giảm buổi lễ liên quan đến việc viết mã Java, đồng thời duy trì cam kết của Java về an toàn kiểu tĩnh, bằng cách cho phép các nhà phát triển bỏ qua tuyên bố thường không cần thiết về các loại biến cục bộ.
var Phạm vi trong JavaCần lưu ý rằng đó varkhông phải là một từ khóa trong Java, mà là một tên loại dành riêng. Như trích dẫn từ JEP 286:
Mã định danh var không phải là một từ khóa; thay vào đó là một tên loại dành riêng. Điều này có nghĩa là mã sử dụng var làm biến, phương thức hoặc tên gói sẽ không bị ảnh hưởng; mã sử dụng var làm tên lớp hoặc tên giao diện sẽ bị ảnh hưởng (nhưng những tên này rất hiếm trong thực tế, vì chúng vi phạm các quy ước đặt tên thông thường).
Lưu ý rằng vì varlà tên loại dành riêng và không phải là từ khóa, nên nó vẫn có thể được sử dụng cho tên gói, tên phương thức và tên biến (cùng với vai trò can thiệp kiểu mới). Ví dụ, sau đây là tất cả các ví dụ về sử dụng hợp lệ vartrong Java:
var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;
Như trích dẫn từ JEP 286:
Điều trị này sẽ được giới hạn ở các biến cục bộ với các bộ khởi tạo, các chỉ mục trong vòng lặp for được tăng cường và các hàm cục bộ được khai báo trong một vòng lặp for truyền thống; nó sẽ không có sẵn cho các biểu mẫu phương thức, các biểu mẫu của hàm tạo, các kiểu trả về của phương thức, các trường, các biểu mẫu bắt hoặc bất kỳ loại khai báo biến nào khác.
vartrong Java & CĐây là một điểm khác biệt đáng chú ý giữa varC # và Java bao gồm: varcó thể được sử dụng làm tên loại trong C # nhưng không thể được sử dụng làm tên lớp hoặc tên giao diện trong Java. Theo tài liệu C # (Nhập ngầm định các biến cục bộ) :
Nếu một loại có tên
varnằm trong phạm vi, thìvartừ khóa sẽ phân giải thành tên loại đó và sẽ không được coi là một phần của khai báo biến cục bộ được gõ ngầm.
Khả năng sử dụng varlàm tên loại trong C # tạo ra một số phức tạp và đưa ra một số quy tắc phân giải phức tạp, được tránh vartrong Java bằng cách không cho phép varlàm tên lớp hoặc giao diện. Để biết thông tin về độ phức tạp của vartên loại trong C #, hãy xem Hạn chế áp dụng cho khai báo biến được nhập ngầm định . Để biết thêm thông tin về lý do đằng sau quyết định phạm vi cho `var trong Java, hãy xem JEP 286: Lựa chọn phạm vi .
varcho các trường hoặc các kiểu trả về không? Tại sao nó quan trọng cần lưu ý?
vartrong Java không thể được sử dụng cho các trường hoặc các kiểu trả về. Điều này rất quan trọng vì hạn chế này làm cho varngữ cảnh nhạy cảm, nơi nó chỉ có thể được sử dụng trong một số bối cảnh (biến cục bộ) chứ không phải các bối cảnh khác. Đây không nhất thiết là một sự khác biệt giữa Java và C # cần lưu ý, nhưng nói chung là một hạn chế quan trọng khi sử dụng vartrong Java.
varmột tên lớp và sử dụng nó như vậy. Về mặt kỹ thuật, đây là một "từ khóa ngữ cảnh" trong trường hợp c #, nhưng trong Java dường như bạn không thể làm như vậy. Sửa tôi nếu tôi sai.
varlàm tên lớp hoặc tên giao diện trong Java (dù sao nó không phổ biến), nhưng bạn có thể sử dụng nó cho tên biến, tên phương thức và tên gói. Ví dụ, var var = 1;là một câu lệnh Java hợp lệ nhưng cố gắng khai báo một lớp là public class var {}kết quả trong một lỗi : as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations. Tôi đã cập nhật câu trả lời ở trên để đi sâu vào chi tiết hơn về lý do đằng sau vartrong Java và sự khác biệt của nó vớivar C #.
Nó sẽ được hỗ trợ trong JDK 10. Thậm chí có thể thấy nó hoạt động trong bản dựng truy cập sớm .
Các JEP 286 :
Tăng cường Ngôn ngữ Java để mở rộng suy luận kiểu đối với khai báo các biến cục bộ với các bộ khởi tạo.
Vì vậy, bây giờ thay vì viết:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
Bạn viết:
var list = new ArrayList<String>();
var stream = myStream();
Ghi chú:
varbây giờ là một tên loại dành riêngNếu bạn muốn dùng thử mà không cần cài đặt Java trên hệ thống cục bộ của mình, tôi đã tạo một hình ảnh Docker với JDK 10 được cài đặt trên nó:
$ 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) không tương đương. Trong varví dụ listlà loại ArrayList, không phải là mộtList .
Một giải pháp đơn giản (giả sử bạn đang sử dụng một IDE tốt) là chỉ cần nhập 'int' ở mọi nơi và sau đó lấy nó để đặt loại cho bạn.
Tôi thực sự vừa thêm một lớp gọi là 'var' vì vậy tôi không phải gõ một cái gì đó khác.
Mã vẫn còn quá dài dòng, nhưng ít nhất bạn không phải gõ nó!
int) - tôi có thiếu điều gì không? (*: trong khi tôi sẽ không bao giờ gọi Eclipse là một IDE tốt, tôi không thể phán xét cho người khác ...)
Java 10 đã nhận được suy luận kiểu biến cục bộ, vì vậy bây giờ nó có var tương đối giống với C # one (theo như tôi biết).
Nó cũng có thể suy ra loại phi denotable (loại trong nước chưa thể có tên trong đó diễn ra bởi các lập trình viên, mặc dù trong đó loại đều là phòng không denotable là khác nhau). Xem ví dụ: Thủ thuật với varvà các lớp ẩn danh (mà bạn không bao giờ nên sử dụng tại nơi làm việc) .
Sự khác biệt tôi có thể tìm thấy là trong C #,
Trong Java 10 varkhông phải là một tên loại hợp pháp.
Tính đến Java 10, tương đương là ... var.
Tôi biết cái này cũ hơn nhưng tại sao không tạo một lớp var và tạo các hàm tạo với các kiểu khác nhau và tùy thuộc vào các hàm tạo nào được gọi mà bạn nhận var với kiểu khác. Bạn thậm chí có thể xây dựng các phương thức để chuyển đổi loại này sang loại khác.
Lombokhỗ trợ var nhưng nó vẫn được phân loại là thử nghiệm:
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);
Đây là một cạm bẫy cần tránh khi cố gắng sử dụng nó trong IntelliJ IDEA. Nó dường như hoạt động như mong đợi mặc dù bao gồm hoàn thành tự động và mọi thứ. Cho đến khi có một giải pháp "không hack" (ví dụ do JEP 286: Suy luận kiểu biến cục bộ ), đây có thể là lựa chọn tốt nhất của bạn ngay bây giờ.
Lưu ý rằng valcũng được hỗ trợ Lombokmà không sửa đổi hoặc tạo một lombok.config.
Bạn có thể, trong Java 10, nhưng chỉ dành cho Cục bộ biến, ý nghĩa,
Bạn có thể,
var anum = 10; var aString = "Var";
Nhưng không thể,
var anull = null; // Since the type can't be inferred in this case
Kiểm tra thông số kỹ thuật để biết thêm.
varcó thể được sử dụng cho nhiều dạng loại không thể khử được, bao gồm loại chụp, loại giao cắt và loại lớp ẩn danh. Và, kể từ Java 11, nó cũng có thể được áp dụng cho các tham số lambda.
Nói chung, bạn có thể sử dụng lớp Object cho bất kỳ loại nào, nhưng bạn đã thực hiện truyền kiểu sau!
ví dụ:-
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);
vartừ bây giờ chính thức trong ngôn ngữ, câu trả lời của bạn cũng đề cập đến cách thức lỗi thời.
Tính năng này hiện có sẵn trong Java SE 10. var tĩnh, loại an toàn cuối cùng đã đưa nó vào thế giới java :)
nguồn: https://www.oracle.com/cor merg / pressrelease / Java-10-032018.html
val(hoặcvar) nếu bạn sử dụng ngôn ngữ "thay thế Java" cụ thể ;-)