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ó var
từ 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.
var
không giống như dynamic
. var
iables vẫn được gõ tĩnh 100%. Điều này sẽ không biên dịch:
var myString = "foo";
myString = 3;
var
cũ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 User
lớp hoặc dẫn xuất trong đó. Rõ ràng, nếu bạn thực hiện User.GetCurrent
trả 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 var
mà 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 var
các tĩnh loại p
luôn luôn là X
trong ví dụ đầu tiên ở trên, nhưng luôn luôn SuperX
trong 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 :-)
var
khô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();
)? var
là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ĩ var
là không rõ ràng thì đó chỉ là vì không sử dụng nó.
var
rấ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
radioButton
trườ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
.
var
như 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.
var
chí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 .
final
khô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 var
trong 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 var
tê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 var
loại dành riêng trong Java gần giống với var
từ 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). var
trong 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 đó var
khô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ì var
là 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ệ var
trong 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.
var
trong Java & CĐây là một điểm khác biệt đáng chú ý giữa var
C # và Java bao gồm: var
có 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
var
nằm trong phạm vi, thìvar
từ 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 var
là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 var
trong Java bằng cách không cho phép var
làm tên lớp hoặc giao diện. Để biết thông tin về độ phức tạp của var
tê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 .
var
cho 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 ý?
var
trong 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 var
ngữ 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 var
trong Java.
var
mộ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.
var
là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 var
trong 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ú:
var
bâ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 var
ví dụ list
là 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 var
và 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 var
khô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.
Lombok
hỗ 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 val
cũng được hỗ trợ Lombok
mà 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.
var
có 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);
var
từ 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ể ;-)