2010-09-27 17 views
5

Tôi thực sự bối rối về cả hai chủ đề, bất cứ ai có thể giải thích cho tôi.autoboxing và generics

ArrayList<Long> queryParms = new ArrayList<Long>(); 
  1. Là một ở trên được gọi là thuốc generic hoặc autoboxing và những gì là unboxing?
  2. Đây có phải là phương pháp hay nhất không?
  3. Một số người nói Autoboxing là điều xấu xa.
  4. Nếu tôi sử dụng Generics, tôi có thể tránh autoboxing và unboxing không?

Trả lời

8
  1. Ở trên là ví dụ về Generics. Auto-boxing sẽ là chuyển đổi tự động, bởi trình biên dịch, thuộc kiểu nguyên thủy trong một loại trình bao bọc và ngược lại. Trong trường hợp của bạn, ví dụ, từ một biến long trong một biến Long:

    long param = 13L; 
    queryParms.add(param); 
    
  2. Sử dụng Generics? Vâng. Nó cho phép bạn chỉ định những gì danh sách của bạn sẽ chứa. Bạn nên sử dụng chúng. Sử dụng auto-boxing? Có, nó đơn giản hóa mã, và bạn không phải lo lắng về việc chuyển đổi giữa các kiểu biến nguyên thủy thành trình bao bọc (và ngược lại).

  3. Tự động đấm bốc không phải là điều xấu (IMHO). Họ là một số trường hợp góc trong đó tự động đấm bốc có thể rất khó chịu, nhưng nếu bạn biết nó hoạt động như thế nào, bạn không cần phải lo lắng về nó. Đây là the Sun (now Oracle) paper on auto-boxing, nếu bạn cần biết thêm về nó.

  4. Nếu bạn muốn tạo danh sách chứa trình bao bọc (trong trường hợp của bạn là Long), bạn sẽ phải xử lý chuyển đổi loại. Bạn có thể sử dụng chuyển đổi loại rõ ràng hoặc bạn có thể sử dụng tự động đấm bốc.

+4

Quyền tự động vô ý (un) có thể là một hog hiệu suất, nếu được thực hiện trong vòng lặp được thực thi nhiều lần. Đây có thể là lý do tại sao một số người coi đó là điều xấu xa. Tuy nhiên, vấn đề thực sự ở đây là viết mã bất cẩn (và thiếu hồ sơ), thay vào đó là tính năng ngôn ngữ. –

+1

Nếu tôi sử dụng generics, tôi có thể tránh autoboxing và unboxing không? – John

+0

@John Bạn có thể tránh autoboxing không cần thiết và unboxing bằng cách xem xét cẩn thận cho dù sử dụng nguyên thủy hoặc wrapper loại và kiểm tra nếu có phương pháp gọi chúng tôi gây ra boxing. Tuy nhiên, vì bạn cần phải sử dụng loại wrapper với generics, thường không có cách nào để tránh nó hoàn toàn. – Carlos

2

Tự động là khi một nguyên thủy được tự động chuyển đổi thành đối tượng. Ví dụ:

Long autoboxedLong = 3; 

Lưu ý trường hợp trên L, làm autoboxedLong đối tượng thay vì nguyên thủy.

Điều ngược lại là tự động unboxing, cho phép bạn viết:

long autounboxedLong = autoboxedLong; 

có nghĩa là bạn tự động chuyển đổi một đối tượng vào một nguyên thủy. Tuy nhiên điều này là nguy hiểm, vì autoboxedLong có thể là null. Sau đó, mã này sẽ ném một NullPointerException.

Ví dụ của bạn không phải là về tự động tạo hộp, nhưng tự động phát đi vào khi bạn chèn các đối tượng vào danh sách của mình. Bạn có thể làm:

queryParams.add(1); 

và autoboxing sẽ tự động hộp nguyên thủy dài 1 thành đối tượng Long.

1

Không nêu trên không được gọi autoboxing.When bạn làm

queryParms.add(22l);//here primitive type 22 is converted to wrapper class Long type.This  
        //is called autoboxing. 
1

Bạn ví dụ tạo ra một ArrayList với kiểu generic Long. Vì vậy, danh sách sẽ chứa các đối tượng kiểu dài. Outoboxing làm cho nguyên thủy từ các đối tượng và ngược lại.Vì vậy, bạn có thể sử dụng danh sách của bạn như:

long x = queryParms.get(0); 

hoặc

queryParams.add(4L); 
0

Trong Java 5.0, lớp wrapper đã trở nên dễ dàng hơn để sử dụng. Java 5.0 đã giới thiệu chuyển đổi tự động giữa kiểu nguyên thủy và lớp trình bao bọc tương ứng.

Từ kiểu nguyên thủy đến lớp trình bao bọc corresponse được gọi là autoboxing, quá trình ngược lại được gọi là unboxing. Tự động và hủy hộp cũng áp dụng cho các cuộc gọi phương thức. Ví dụ, bạn có thể chuyển đối số kiểu int cho một phương thức có tham số chính thức của kiểu Integer.

  • Ngoại lệ NullpointerException xảy ra Khi bỏ hộp tham chiếu lớp bao bọc rỗng thành kiểu nguyên thủy. Ví dụ, mã sẽ biên dịch nhưng nó sẽ ném một NullpointerException vào thời gian chạy.

    Long L = null; long l = L; ... 
    
  • Chuyển đổi quyền anh chuyển giá trị của kiểu gốc thành giá trị tương ứng của loại tham chiếu. Nhưng các kiểu nguyên thủy không thể được mở rộng/Thu hẹp thành các lớp Wrapper và ngược lại. Ví dụ:

    byte b = 43; Số nguyên I1 = 23; // Giá trị nguyên không đổi Integer I2 = (int) b; // Truyền tới loại int Long L1 = 23; // biên dịch lỗi vì 23 là giá trị số nguyên Long L2 = (Long) 23; // không thể truyền giá trị số nguyên thành lớp bao bọc dài Long L3 = 23L; Dài L4 = (dài) 23;

Hạn chế này cũng được áp dụng cho phương pháp gọi:

public class MyClass 
{ 
    public void method(Long i) 
    { 
     System.out.println("Here"); 

    } 
    public static void main(String[] args) 
    { 
     MyClass s = new MyClasslass(); 
     //s.method(12); 
     // error  s.method(12L); 
     // ok 
    } 

} 
•When invoking a method from multiple overloading methods, For the matching method process, the Java compiler will perferance the order of primitive types (Widening Primitive Conversion), wrapper class (Boxing Conversion), and var-args. For example, 
public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(long x, long y) 
    { 
     System.out.println("method(long x, long y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Kết quả là method(long x, long y). Trình biên dịch Java sẽ kiểm tra các kiểu nguyên thủy phù hợp, sau đó nó sẽ tìm kiếm các kiểu Wrapper.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Kết quả là method(Long x, Long y). Trình biên dịch Java ưu tiên cho chữ ký của phương thức lớp Wrapper phù hợp với phương thức khác với phương thức varargs nguyên thủy.

public class MyClass 
{ 
    public void method(Double x, Double y) 
    { 
     System.out.println("method(Double x, (Double y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Kết quả là method(long ...x). Trình biên dịch sẽ không thu hẹp giá trị nguyên thủy "dài" thành "int"; Ngoài ra, nó không thể kéo dài đến lớp đôi. Chỉ có thể sử dụng phương thức var-args.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public static void main(String[] args) 
    { 
     int x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Đối số không thể chuyển thành "dài" và sau đó là "Long". Bạn sẽ nhận được lỗi biên dịch.

  • Để tiết kiệm bộ nhớ, hai trường hợp của các đối tượng bao bọc sau sẽ luôn là == khi giá trị nguyên thủy của chúng giống nhau. Vui lòng đọc Tại sao chuyển đổi tự động đôi khi trả lại cùng một tham chiếu?
+0

Vui lòng định dạng này. Xem trang định dạng wiki: http://stackoverflow.com/editing-help – mtk