Có một phương pháp hoặc phương pháp tương đương Java cho từ khóa typedef trong C ++ không?


244

Đến từ nền tảng C và C ++, tôi thấy việc sử dụng hợp lý typedeflà vô cùng hữu ích. Bạn có biết một cách để đạt được chức năng tương tự trong Java, cho dù đó là cơ chế, mẫu hoặc một số cách hiệu quả khác mà bạn đã sử dụng?


6
typedef có thể được sử dụng hoặc nhiều thứ, tốt và xấu, mặc dù không phải ai cũng đồng ý với cái nào. Bạn có phiền khi nói những khía cạnh nào của typedef mà bạn nghĩ là có giá trị không? Bằng cách đó, chúng tôi có thể cho bạn biết làm thế nào để có được các hiệu ứng tương tự trong Java hoặc tại sao đó là điều bạn không muốn làm trong Java. Bộ sưu tập các câu trả lời bên dưới mỗi giả định bạn đang nói về việc sử dụng yêu thích (hoặc bị ghét nhất) của tác giả.
PanCrit

3
Tôi thích gõ các kiểu bản địa nếu sau này tôi có thể biến nó thành một lớp. typedef IndexT int; ví dụ. Sau này, nếu tôi muốn IndexT là một lớp, tôi chỉ cần thực hiện nó và loại bỏ typedef. Nó giúp che giấu thông tin.
JR Lawhorne

13
@Alexander - liên kết được cập nhật: ibm.com/developerworks/java/l
Library / j-jtp02216 / index.html

1
Tôi không chắc những nhược điểm của việc này là gì, nhưng:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff

2
Bạn có thể thích Scala stackoverflow.com/a/21223102/203968
oluies

Câu trả lời:


112

Java có các kiểu nguyên thủy, các đối tượng và mảng và đó là nó. Không có typedefs.


37
Tôi đoán hầu hết mọi người muốn typedefxác định lại booleanđể bool.
Tomáš Zato - Phục hồi Monica

66
@ TomášZato Tôi không biết hầu hết mọi người, nhưng theo kinh nghiệm của tôi, thật hữu ích khi thêm ngữ nghĩa như: typedef int PlayerIDcho phép trình biên dịch đảm bảo PlayerID không được sử dụng thay thế cho các int khác và nó cũng giúp mã dễ đọc hơn cho con người . Về cơ bản, nó giống như một enum nhưng không có một bộ giá trị giới hạn.
weberc2

76
@ TomášZato Nó cũng hữu ích để rút ngắn các loại dài như typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek

32
@ weberc2 "cho phép trình biên dịch đảm bảo PlayerID không được sử dụng thay thế cho các int khác" - typedefkhông kích hoạt bất kỳ thứ gì như vậy. Nó chỉ đưa ra một tên khác cho một loại.
emlai

7
Cũng hữu ích nếu, ví dụ, bạn có một số loại ID intvà bạn cần thay đổi nó thành long, bạn phải thay đổi nó ở mọi nơi trong mã nơi bạn làm việc với ID. Nếu bạn có typedef, bạn chỉ phải thay đổi nó ở 1 nơi.
Jardo

101

Nếu đây là ý của bạn, bạn chỉ cần mở rộng lớp bạn muốn gõ, ví dụ:

public class MyMap extends HashMap<String, String> {}

5
Tôi tranh luận liệu đây có phải là mô hình chống lại nhiều hơn so với sử dụng typedef trong C.
Zed

22
Nó chắc chắn là - typedefkhông có vấn đề nào mà bài viết mô tả cho các lớp giả mạo đó (và chúng rất thật).
Pavel Minaev

30
@Andreas_D: liên kết của bạn, đã được sửa: ibm.com/developerworks/java/l
Janus Troelsen

7
Tôi thích điều này vì lý do tương tự tôi thích typedefs. Nếu bạn có một thùng chứa các đối tượng, có thể dễ dàng trao đổi các loại container bằng cách thay đổi typedef. Ngoài ra, nó có thể trừu tượng container cho người dùng cuối (đôi khi là mong muốn). Tôi thường sẽ làm điều này bên trong một lớp khác, vì vậy kiểu này trở nên rõ ràng hơn (ví dụ MyTree.Branches, trong đó Chi nhánh lớp mở rộng Hashset <MyTree> {})
Josh Petitt

8
Mặc dù vấn đề chính của phương pháp này là bạn không thể sử dụng nó với finalcác lớp.
AJMansfield

14

Không có typedef trong java kể từ 1.6, điều bạn có thể làm là tạo một lớp bao bọc cho những gì bạn muốn vì bạn không thể phân lớp các lớp cuối cùng (Integer, Double, v.v.)


3
Bài viết chống mẫu được tham chiếu dựa trên giả định rằng bạn chỉ muốn rút ngắn cách gõ của mình (điều này thực sự sẽ ẩn thông tin loại hữu ích). Công dụng thực sự mà hầu hết mọi người muốn là phân tán các loại và để trình biên dịch thực hiện công việc của nó cho bạn. Xem IndexT ở trên. công khai hóa đơn fetchInvoiceItem (Chuỗi, Chuỗi, Chuỗi); so với hóa đơn công khai fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Các loại rõ ràng cộng với Bộ chuyển đổi / Trình xác thực giúp lập trình API Web trong đó MỌI THỨ bắt đầu dưới dạng Chuỗi an toàn hơn rất nhiều.
englebart

Không có toán tử tải ovel trong java, vì vậy nó trở nên xấu xí
mils

9

Như những người khác đã đề cập trước đây,
không có cơ chế typedef trong Java.
Tôi cũng không hỗ trợ "các lớp giả" nói chung, nhưng không nên có một quy tắc nghiêm ngặt chung ở đây:
Nếu ví dụ mã của bạn sử dụng nhiều lần và hơn một "loại dựa trên chung" chẳng hạn:

Map<String, List<Integer>> 

Bạn chắc chắn nên xem xét việc có một lớp con cho mục đích đó.
Một cách tiếp cận khác mà người ta có thể xem xét, ví dụ như để mã của bạn giảm tốc như:

//@Alias Map<String, List<Integer>>  NameToNumbers;

Và sau đó sử dụng trong mã NameToNumbers của bạn và có một tác vụ biên dịch trước (ANT / Gradle / Maven) để xử lý và tạo mã java có liên quan.
Tôi biết rằng với một số độc giả của câu trả lời này nghe có vẻ lạ, nhưng đây là cách mà nhiều khung đã triển khai "chú thích" trước JDK 5, đây là điều mà lombok đang làm và các khung khác.


5

Thực sự, việc sử dụng typedef duy nhất mang đến Javaland là bí danh - nghĩa là, đưa ra cùng một tên nhiều lớp. Đó là, bạn đã có một lớp "A" và bạn muốn "B" đề cập đến điều tương tự. Trong C ++, bạn sẽ thực hiện "typedef BA;"

Thật không may, họ không hỗ trợ nó. Tuy nhiên, nếu bạn kiểm soát tất cả các loại liên quan, bạn CÓ THỂ kéo một vụ hack khó chịu ở cấp thư viện - bạn có thể mở rộng B từ A hoặc B thực hiện A.


14
typedefcũng sẽ hữu ích để tạo bí danh cho các loại chung chung. Ví dụ: typedef A<Long,String> B;(đây có thể là trường hợp đặc biệt của những gì bạn đã mô tả, nhưng nó cho thấy sự hấp dẫn của ý tưởng rõ ràng hơn một chút).
igorrs

Trong trường hợp sử dụng của tôi, tôi muốn đưa ra bí danh cho các kiểu nguyên thủy. real_tcho doubleboolcho boolean.
Aaron Franke

3

Có lẽ đây có thể là một sự thay thế khả dĩ khác:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}

2
Bạn không nghĩ rằng điều này bây giờ có vấn đề bởi vì bất cứ khi nào bạn xác định myMapthể hiện của loại MyMap, bạn chỉ có thể hoạt động trên HashMap thực tế bằng cách nhập myMapInstance.value.SomeOperation()thay vì myMapInstance.SomeOperation(). Điều này thật khó chịu phải không?
thủy ngân0114

2
bạn vẫn có thể thực hiện myMapInstance.SomeOperation () - đây là những gì @Delegate dành cho
shrewquest

3

Như đã lưu ý trong các câu trả lời khác, bạn nên tránh các antipotype giả . Tuy nhiên, typedefs vẫn hữu ích ngay cả khi đó không phải là cách để đạt được chúng. Bạn muốn phân biệt giữa các loại trừu tượng khác nhau có cùng biểu diễn Java. Bạn không muốn trộn lẫn các chuỗi là mật khẩu với các chuỗi là địa chỉ đường phố hoặc số nguyên biểu thị phần bù với các chuỗi có giá trị tuyệt đối.

Các Checker Khung phép bạn xác định một typedef trong một cách tương thích ngược. Tôi làm việc ngay cả đối với các lớp nguyên thủy như intvà các lớp cuối cùng như String. Nó không có chi phí thời gian chạy và không phá vỡ các bài kiểm tra bình đẳng.

Các bí danh Loại và typedefs trong hướng dẫn Khung kiểm tra mô tả một số cách để tạo typedefs, tùy thuộc vào nhu cầu của bạn.




-6

Bạn có thể sử dụng Enum, mặc dù về mặt ngữ nghĩa khác một chút so với typedef ở chỗ nó chỉ cho phép một bộ giá trị bị hạn chế. Một giải pháp khả thi khác là một lớp bao bọc có tên, vd

public class Apple {
      public Apple(Integer i){this.i=i; }
}

nhưng điều đó có vẻ khó hiểu hơn, đặc biệt là do mã không rõ ràng rằng lớp không có chức năng nào khác ngoài bí danh.


-7

Typedef cho phép các mục được gán ngầm cho các loại mà chúng không. Một số người cố gắng khắc phục điều này bằng các tiện ích mở rộng; đọc ở đây tại IBM để được giải thích tại sao đây là một ý tưởng tồi.

Chỉnh sửa: Mặc dù suy luận kiểu mạnh là một điều hữu ích, tôi không nghĩ (và hy vọng chúng ta sẽ không) thấy typedef cái đầu xấu xí trong các ngôn ngữ được quản lý (bao giờ?).

Chỉnh sửa 2: Trong C #, bạn có thể sử dụng câu lệnh sử dụng như thế này ở đầu tệp nguồn. Nó được sử dụng để bạn không phải thực hiện mục thứ hai được hiển thị. Lần duy nhất bạn thấy thay đổi tên là khi một phạm vi giới thiệu xung đột tên giữa hai loại. Việc đổi tên được giới hạn trong một tệp, bên ngoài mà mọi loại biến / tham số được sử dụng đều được biết đến với tên đầy đủ của nó.

using Path = System.IO.Path;
using System.IO;

23
"Typedef cho phép các mục được gán ngầm cho các loại không phải là" Cái gì? Typedef chỉ đơn giản cho phép bạn tạo một tên khác dưới dạng bí danh cho loại. Các loại vẫn giống hệt nhau, bạn chỉ cần có một tên ngắn hơn cho nó. Nó không có gì để làm với suy luận kiểu. -1
jalf

@jalf: Trên thực tế, suy luận kiểu được sử dụng làm giải pháp cho chính xác những gì bạn đang nói, nhưng tôi đã đưa ra một ví dụ khác về việc bạn có thể sử dụng "typedef" để khắc phục xung đột tên.
Sam Harwell

1
liên kết được cập nhật: ibm.com/developerworks/java/l Library / j
Alexander Malakhov

@AlexanderMalakhov Cảm ơn, tôi đã tiếp tục và cập nhật câu trả lời với liên kết của bạn
Dave McClelland

-14

Không cần typedef trong Java. Tất cả mọi thứ là một đối tượng ngoại trừ nguyên thủy. Không có con trỏ, chỉ có tài liệu tham khảo. Các tình huống mà bạn thường sử dụng typedefs là các trường hợp bạn tạo đối tượng thay thế.


19
Không, nhu cầu về typedef vẫn tồn tại nếu bạn muốn một tên ngắn hơn cho một loại. Hoặc chỉ khi bạn muốn có thể thay thế việc sử dụng một loại bằng một loại khác bằng cách thay đổi một nơi trong mã nguồn.
jalf

28
@Bill K: meh, nói rằng sau khi bạn phải gõ một cái gì đó như std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string >>> :: const_iterator a vài lần. Trong trường hợp đó, một typedef rút ngắn tên giúp tăng cường khả năng đọc, không cản trở nó.
Joel

22
Đổi tên một loại có thể cải thiện đáng kể khả năng đọc. Điều gì dễ đọc và dễ hiểu hơn (và do đó dễ đọc hơn :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>hay IncrediblyFancyGraph? Tôi luôn có thể tham khảo định nghĩa để tìm hiểu xem nó thực sự là về cái gì. Bằng cách đó tôi cũng có thể chắc chắn rằng mình sẽ không bỏ lỡ UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>sự nhàm chán tuyệt đối.
Aleksandar Dimitrov

10
@AleksandarDimitrov Tôi biết rằng nhận xét của bạn đã gần 3 tuổi khi tôi nhập bài này, nhưng tôi cảm thấy rất quan trọng để chỉ ra cách ví dụ đó là giả tạo và không thực tế: không có tên lớp nào trong số đó có chứa từ đó Enterprise.
Casey

4
Tên xấu cản trở khả năng đọc. Tên tốt giúp. Typedefs có thể giúp nếu tên đầy đủ quá dài đến nỗi khó đọc hoặc làm hỏng định dạng mã của bạn. Nó cũng sẽ giúp ích khi tương tác với các tên lớp không rõ ràng hoặc không rõ ràng của người khác. Nếu bạn thực sự tin rằng một typedef vốn đã làm cho mã của bạn không thể đọc được, thì bạn cũng nên tin rằng bạn không bao giờ nên sử dụng các câu lệnh nhập khẩu và phải luôn luôn tham khảo các tên lớp đủ điều kiện.
Christopher Barber
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.