Trong Java, kết quả của việc thêm hai ký tự là int hay char?


80

Khi thêm 'a' + 'b'nó tạo ra 195. Là kiểu dữ liệu đầu ra charhay int?


2
Nếu loại được charthì giá trị của 'a' + 'b'sẽ không được 195nhưng'Ã'
Joren

1
Nó là 195 trên đây - ideone.com nhưng không phải trong Eclipse.
màu cam,

2
Bạn đọc điều đó từ cuốn sách Thuật toán lol! Tôi đến đây chính xác là vì bài tập này;)
Jack Twain

Câu trả lời:


132

Kết quả của việc thêm ký tự Java, quần short hoặc byte là một int :

Đặc tả ngôn ngữ Java về Quảng cáo số nhị phân :

  • Nếu bất kỳ toán hạng nào thuộc loại tham chiếu, chuyển đổi mở hộp (§5.1.8) được thực hiện. Sau đó:
  • Nếu một trong hai toán hạng thuộc loại double, toán hạng kia được chuyển thành double.
  • Ngược lại, nếu một trong hai toán hạng là kiểu float, thì toán hạng còn lại sẽ được chuyển thành float.
  • Ngược lại, nếu một trong hai toán hạng thuộc loại dài, toán hạng còn lại được chuyển thành dài.
  • Nếu không, cả hai toán hạng đều được chuyển đổi thành kiểu int.

Nhưng hãy lưu ý những gì nó nói về các toán tử gán ghép (như + =) :

Kết quả của phép toán nhị phân được chuyển đổi thành kiểu của biến bên trái ... và kết quả của phép chuyển đổi được lưu trữ vào biến.

Ví dụ:

char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK

Nói chung, bạn có thể tìm ra loại kết quả là truyền nó tới một Đối tượng và hỏi nó thuộc lớp nào:

System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer

Nếu bạn quan tâm đến hiệu suất, hãy lưu ý rằng mã bytecode của Java thậm chí không có các hướng dẫn dành riêng cho số học với các kiểu dữ liệu nhỏ hơn. Ví dụ, để thêm vào, có các hướng dẫn iadd(cho ints), ladd(cho longs), fadd(cho float), dadd(cho double), và thế là xong. Để mô phỏng x += yvới các kiểu nhỏ hơn, trình biên dịch sẽ sử dụng iaddvà sau đó bằng không các byte phía trên của int bằng cách sử dụng một lệnh như i2c("int to char"). Nếu CPU gốc có hướng dẫn dành riêng cho dữ liệu 1 byte hoặc 2 byte, thì máy ảo Java sẽ tối ưu hóa cho dữ liệu đó tại thời điểm chạy.

Nếu bạn muốn nối các ký tự dưới dạng một Chuỗi thay vì diễn giải chúng dưới dạng kiểu số, có rất nhiều cách để thực hiện điều đó. Cách dễ nhất là thêm một Chuỗi trống vào biểu thức, bởi vì việc thêm một ký tự và một Chuỗi dẫn đến một Chuỗi. Tất cả các biểu thức này dẫn đến Chuỗi "ab":

  • 'a' + "" + 'b'
  • "" + 'a' + 'b'(điều này hoạt động vì "" + 'a'được đánh giá đầu tiên; nếu ""ở cuối thay vào đó bạn sẽ nhận được "195")
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')


7

Bạn có thể muốn tìm hiểu các biểu thức sau đây về char.

char c='A';
int i=c+1;

System.out.println("i = "+i);

Điều này hoàn toàn hợp lệ trong Java và trả về 66, giá trị tương ứng của ký tự (Unicode) của c+1.


String temp="";
temp+=c;
System.out.println("temp = "+temp);

Điều này quá hợp lệ trong Java và biến kiểu Chuỗi temptự động chấp nhận ckiểu char và tạo ra temp=Atrên bảng điều khiển.


Tất cả các câu lệnh sau đây cũng hợp lệ trong Java!

Integer intType=new Integer(c);
System.out.println("intType = "+intType);

Double  doubleType=new Double(c);
System.out.println("doubleType = "+doubleType);

Float floatType=new Float(c);
System.out.println("floatType = "+floatType);

BigDecimal decimalType=new BigDecimal(c);
System.out.println("decimalType = "+decimalType);

Long longType=new Long(c);
System.out.println("longType = "+longType);

Mặc dù clà một kiểu char, nhưng nó có thể được cung cấp mà không có lỗi trong các hàm tạo tương ứng và tất cả các câu lệnh trên đều được coi là câu lệnh hợp lệ. Chúng tạo ra các đầu ra tương ứng như sau.

intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65

charlà một kiểu tích phân số nguyên thủy và như vậy phải tuân theo tất cả các quy tắc của những con thú này bao gồm chuyển đổi và thăng hạng. Bạn sẽ muốn đọc về điều này và JLS là một trong những nguồn tốt nhất cho việc này: Chuyển đổi và Quảng cáo . Đặc biệt, hãy đọc đoạn ngắn về "5.1.2 Mở rộng Chuyển đổi Nguyên thủy".


3

Trình biên dịch Java có thể hiểu nó là một trong hai.

Kiểm tra bằng cách viết chương trình và tìm lỗi trình biên dịch:

public static void main(String[] args) {
    int result1 = 'a' + 'b';
    char result2 = 'a' + 'b';
}

Nếu đó là một ký tự, thì dòng đầu tiên sẽ cho tôi lỗi và dòng thứ hai thì không. Nếu đó là một int, thì điều ngược lại sẽ xảy ra.

Tôi đã biên dịch nó và tôi đã ..... KHÔNG CÓ LỖI. Vì vậy, Java chấp nhận cả hai.

Tuy nhiên, khi tôi in chúng, tôi nhận được:

int: 195

char: Ã

Điều gì sẽ xảy ra khi bạn làm:

char result2 = 'a' + 'b'

một chuyển đổi ngầm được thực hiện (một "chuyển đổi thu hẹp nguyên thủy" từ int sang char ).


Tôi ngạc nhiên khi bạn không nhận được cảnh báo trình biên dịch trong trường hợp thứ hai về khả năng mất độ chính xác do thu hẹp.
Hot Licks

@eboix: bạn đã viết "trình biên dịch tự động chuyển thành char hoặc int" [sic] ... Điều này không đúng vì int không được "cast" thành int và việc chuyển từ int sang char không được gọi một "diễn viên" nhưng là một "chuyển đổi nguyên thủy thu hẹp"; )
TacticalCoder

Vâng. Tôi cũng đã mong đợi điều đó. Tôi thực sự đã viết một phần câu trả lời của mình về điều đó trước khi tạo chương trình của mình, nhưng sau đó tôi đã xóa nó khi thấy rằng tôi không nhận được cảnh báo hoặc lỗi nào.
eboix

@eboix: eh eh:) Tôi đã chỉnh sửa nó nhưng tôi chưa có 2.000 điểm danh tiếng, do đó nhận xét của tôi thay vì chỉnh sửa; )
TacticalCoder

Nếu bạn muốn, @ user988052, tôi có thể thay đổi nó trở lại như cũ và bạn có thể chỉnh sửa nó, nhận được điểm. Bạn vẫn có thể chỉnh sửa nó nếu bạn có ít hơn 2000 điểm danh tiếng. Chỉ có điều là người thực hiện bài phải chấp nhận chỉnh sửa. Tôi sẽ thay đổi lại nó ngay bây giờ để bạn có thể nhận được hai điểm đúng là của bạn.
eboix

1

Theo quy tắc thăng hạng nhị phân , nếu không có toán hạng nào là kép, float hoặc long, thì cả hai đều được thăng thành int. Tuy nhiên, tôi thực sự khuyên bạn không nên coi kiểu char là số, kiểu đó làm mất mục đích của nó.


1
Việc sử dụng charnhư một giá trị số hoàn toàn nằm trong mục đích của nó, đó là lý do tại sao JLS dành rất nhiều chi tiết cho việc sử dụng như vậy.
Lew Bloch

1

Mặc dù bạn đã có câu trả lời chính xác (được tham chiếu trong JLS), đây là một đoạn mã để xác minh rằng bạn nhận được một intkhi thêm hai chars.

public class CharAdditionTest
{
    public static void main(String args[])
    {
        char a = 'a';
        char b = 'b';

        Object obj = a + b;
        System.out.println(obj.getClass().getName());
    }
}

Đầu ra là

java.lang.Integer


Đây không phải là một xác minh thuyết phục, bởi vì bạn đã ném một chuyển đổi quyền anh vào hỗn hợp. Các loại intIntegerkhông giống nhau. Một xác minh thuyết phục hơn là cố gắng gán a + bcho một intbiến hoặc một charbiến. Sau đó đưa ra một lỗi biên dịch có hiệu lực là "bạn không thể gán một intcho một char".
Stephen C

0

charđược biểu diễn dưới dạng Unicodegiá trị và trong đó giá trị Unicode được biểu thị \ubằng Hexadecimalgiá trị theo sau .

Là bất kỳ phép toán số học nào trên charcác giá trị được thăng cấp int, do đó, kết quả của 'a' + 'b'được tính như

1.) Áp dụng các Unicodegiá trị trên tương ứng charbằng cách sử dụngUnicode Table

2.) Áp dụng chuyển đổi Hệ thập lục phân sang Hệ thập phân và sau đó thực hiện thao tác trên Decimalcác giá trị.

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

Thí dụ

0061

(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (1 * 16 0 )

(0 * 4096) + (0 * 256) + (6 * 16) + (1 * 1)

0 + 0 + 96 + 1 = 97

0062

(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (2 * 16 0 )

(0 * 4096) + (0 * 256) + (6 * 16) + (2 * 1)

0 + 0 + 96 + 2 = 98

Vì thế 97 + 98 = 195


Ví dụ 2

char        Unicode      Decimal
 Ջ           054b         1355
 À           00c0          192 
                      --------
                          1547    +
                          1163    -
                             7    /
                        260160    *
                            11    %

Đây không phải là những gì câu hỏi đang hỏi về.
Stephen C

FYI, Phản hồi chi tiết của tôi cho nhận xét trên đã bị xóa bởi các mod giải thích lý do đằng sau việc di chuyển câu trả lời của tôi khỏi một bài đăng đã bị xóa. Nếu phản hồi của tôi đã bị xóa để che đậy những sai sót của SO kiểm duyệt thì ít nhất bạn có thể xóa nhận xét trên hoặc chỉ ra khán giả bằng cách nào đó để tôi không phải viết bình luận khác không? câu hỏi cho SO mod
Pavneet_Singh

Tôi đứng về phía bình luận của tôi. Như tôi đã trả lời bạn ... nhưng sau đó bị xóa ... lý do bạn đăng Câu hỏi này ở đây không thay đổi thực tế là nó lạc đề 95% so với câu hỏi và 5% lặp lại các câu trả lời trước đó. Nếu bạn muốn lưu lại kết quả của nỗ lực đã lãng phí của mình, bạn nên lưu nó vào ổ cứng của mình. Hoặc tìm một số câu hỏi khác mà nó có liên quan.
Stephen C

Nếu bạn hiểu rõ về những người kiểm duyệt, hãy xem nó trong meta.stackoverflow.com. Và cung cấp bằng chứng. Tất cả những gì tôi đang cố gắng làm ở đây là dọn dẹp >> cái này << Q&A.
Stephen C

Tôi hiểu quan điểm của bạn nhưng không thể hiểu thực tế là bỏ qua các chi tiết về chuyển đổi Unicode với các ví dụ, vì một giá trị bổ sung có thể giúp ích cho một số độc giả, vì vậy tôi muốn giữ câu trả lời này (Tôi hiểu rằng nó không hữu ích cho bạn và có vẻ như- đề tài). Tôi tránh meta và những nơi tương tự vì không dễ làm những việc như vậy mà không có sức mạnh hoặc sự hỗ trợ, điều này mất rất nhiều thời gian và công sức. Tôi muốn giữ sự bình yên bên trong của mình hơn thưa ngài
Pavneet_Singh

0

Trong khi câu trả lời của Boann là đúng, có một sự phức tạp áp dụng cho trường hợp các biểu thức hằng khi chúng xuất hiện trong ngữ cảnh gán .

Hãy xem xét các ví dụ sau:

  char x = 'a' + 'b';   // OK

  char y = 'a';
  char z = y + 'b';     // Compilation error

Điều gì đang xảy ra? Họ có ý nghĩa giống nhau phải không? Và tại sao việc gán một intcho một chartrong ví dụ đầu tiên là hợp pháp ?

Khi một biểu thức hằng xuất hiện trong ngữ cảnh gán, trình biên dịch Java sẽ tính giá trị của biểu thức và xem nó có nằm trong phạm vi của kiểu mà bạn đang gán hay không. Nếu đúng như vậy, thì một chuyển đổi nguyên thủy thu hẹp ngầm được áp dụng.

  • Trong ví dụ đầu tiên, 'a' + 'b'là một biểu thức hằng và giá trị của nó sẽ phù hợp với a char, vì vậy trình biên dịch cho phép thu hẹp ngầm định intkết quả biểu thức thành a char.

  • Trong ví dụ thứ hai, ylà một biến vì vậy y + 'b'KHÔNG phải là một biểu thức hằng. Vì vậy, mặc dù Blind Freddy có thể thấy rằng giá trị sẽ phù hợp, trình biên dịch KHÔNG cho phép thu hẹp ngầm định nào và bạn gặp lỗi biên dịch nói rằng intkhông thể gán giá trị cho a char.

Có một số cảnh báo khác về thời điểm cho phép chuyển đổi nguyên thủy thu hẹp ngầm định trong ngữ cảnh này; xem JLS 5.2JLS 15.28 để biết chi tiết đầy đủ.

Phần sau giải thích chi tiết các yêu cầu đối với một biểu thức hằng . Nó có thể không phải là những gì bạn có thể nghĩ. (Ví dụ: chỉ khai báo yfinalkhông giúp ích gì.)

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.