2013-08-11 4 views
16

У меня 2 вопроса с этим кодом сегментовПоследний параметр в методе в Java

  1. метод 1 работает нормально и метод 2 не делает. Что является причиной этого?
  2. В возвращаемом значении метода 1 байт (8 бит). Но мы фактически возвращаем значение char (16 бит). Что на самом деле происходит здесь?

// Метод 1

static byte m1() { 
    final char c = 'b'-'a'; 
    return c; 
} 

// Метод 2

static byte m3(final char c) { 
    return c; // 3 
} 
+3

Что вы имеете в виду, если не работаете? –

+1

при компиляции: говорит: ошибка: возможная потеря точности – chathura

+0

Возможно статическая оптимизация в методе 1? –

ответ

23

char в Java является 16 бит без знака значение а, в то время как byte является 8-битное значение. Допустимый диапазон для байта: [-128, 127]. Таким образом, не все символы могут быть назначены в byte.

В своем первом методе вы возвращаете char с кодовом = 1 ('b' - 'a'). Теперь, поскольку вы определили char как final и присвоили ему постоянное выражение, оно становится постоянной времени компиляции. Таким образом, компилятор не дает ошибок компилятора.

От JLS Section 5.2:

If the expression is a constant expression (§15.28) of type byte, short, char, or int:
- A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

выделено мной.

Однако, если вы сделаете c неконечное, это также приведет к ошибке компилятора:

static byte m1() { // This will be an error 
    char c = 'b'-'a'; 
    return c; 
} 

Причина заключается в том, c не компилирование постоянной времени больше, и компилятор не делает неявное понижение.

Во втором методе вы возвращаете char, который вы передали. Параметр c не имеет постоянной времени компиляции. Во время компиляции неизвестно, какое значение может получить метод. Нравится, если вы передадите char с кодовыми точками, не входящими в диапазон допустимых значений byte, это не сработает.

Для того, чтобы 2-й метод работы, вы можете сделать явное приведение:

static byte m3(final char c) { 
    return (byte)c; // 3 
} 
+0

@Babai. Неа. Никогда не работал над Ruby. Я человек Java. –

+0

Ох! в какой компании вы находитесь? –

+0

@Babai. Infosys. –

1

В методе 2, компилятор не может сделать сужающийся неявный бросок из чата в байты, так как это может привести к потере точность (Java поддерживает символы Unicode и его примитивный тип char определяется размером 16 бит информации, в отличие от языка C, где обычно 8 бит)

В способе 1, однако, компилятор может определить, что постоянное значение 'b' - 'a' на самом деле не приведет к потере точности, и поэтому позволяет выполнять неявный перевод.

Взгляните: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

2

В m1() компилятор видит, что char c постоянен со значением 1 и, следовательно, не жалуется, как он знает, что он может быть установлен в байте. Если вы изменили его на final char c = 128, где 127 - максимальный размер byte, вы получите жалобу, так же как и вы, если вы удалили дескриптор переменной final с char c.

+0

Можете ли вы объяснить, почему произошла ошибка, когда окончательное ключевое слово удалено? – chathura

+0

Когда вы удаляете 'final', он больше не является константой. Поэтому компилятор не может быть уверен, что он не изменится в будущем (хотя метод заканчивается в следующей строке, компилятор не знает об этом). Когда есть «final char c» с назначенным значением, компилятор просто видит его как число 127, у которого нет проблем, чтобы безопасно преобразовать его в любой целочисленный тип. Помните, что 'char' в java варьируется от 0 до 65 535, так как он имеет 16 бит. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html –

0

Теперь причина m1() работ и m3() нет, потому что в m1() c является compile-time constant.

Анализ этот код:

byte b = 'x'; //compile-time constant 
    int i = 'x'; //compile-time constant 
    char c = 'x'; //compile-time constant 
    c = i; //compilation error 
    c = b; //compilation error 
    b = i; //compilation error 
    b = c; //compilation error 
    i = b; // Okay 
    i = c; // Okay 

Компилятор не будет делать неявный бросок, который может, возможно, привести к потере данных, для выполнения временных переменных.

Смежные вопросы