Java cast fail exception

How to Solve Class Cast Exceptions in Java?

An unexcepted, unwanted event that disturbed the normal flow of a program is called Exception. Most of the time exceptions are caused by our program and these are recoverable. Example: If our program requirement is to read data from the remote file locating at the U.S.A. At runtime, if the remote file is not available then we will get RuntimeException saying fileNotFoundException. If fileNotFoundException occurs we can provide the local file to the program to read and continue the rest of the program normally.

There are mainly two types of exception in java as follows:

1. Checked Exception: The exception which is checked by the compiler for the smooth execution of the program at runtime is called a checked exception. In our program, if there is a chance of rising checked exceptions then compulsory we should handle that checked exception (either by try-catch or throws keyword) otherwise we will get a compile-time error.

Examples of checked exceptions are classNotFoundException, IOException, SQLException etc.

2. Unchecked Exception: The exceptions which are not checked by the compiler, whether programmer handling or not such type of exception are called an unchecked exception.

Examples of unchecked exceptions are ArithmeticException, ArrayStoreException etc.

Whether the exception is checked or unchecked every exception occurs at run time only if there is no chance of occurring any exception at compile time.

ClassCastException: It is the child class of RuntimeException and hence it is an unchecked exception. This exception is rise automatically by JVM whenever we try to improperly typecast a class from one type to another i.e when we’re trying to typecast parent object to child type or when we try to typecast an object to a subclass of which it is not an instance.

Источник

Объяснение ClassCastException в Java

Давайте подробнее рассмотрим исключение ClassCastException.

Автор: Cristian Stancalau
Дата записи

1. Обзор

В этом коротком уроке мы сосредоточимся на ClassCastException , общем исключении Java .

ClassCastException – это непроверенное исключение , которое сигнализирует о том, что код попытался привести ссылку на тип, к которому он не является подтипом .

Давайте рассмотрим некоторые сценарии, которые приводят к возникновению этого исключения, и как мы можем их избежать.

2. Явный Кастинг

Для наших следующих экспериментов рассмотрим следующие классы:

2.1. Классы литья

Безусловно, наиболее распространенный сценарий встречи с ClassCastException явно приводит к несовместимому типу.

Например, давайте попробуем бросить Лягушку в Млекопитающее :

Мы могли бы ожидать здесь ClassCastException , но на самом деле мы получаем ошибку компиляции: “несовместимые типы: Лягушка не может быть преобразована в млекопитающее”. Однако ситуация меняется, когда мы используем общий супертип:

Теперь мы получаем ClassCastException из второй строки:

Проверенное значение Mammal несовместимо со ссылкой Frog , поскольку Frog не является подтипом Mammal . В этом случае компилятор не может нам помочь, так как переменная Animal может содержать ссылку совместимого типа.

Интересно отметить, что ошибка компиляции возникает только тогда, когда мы пытаемся привести к однозначно несовместимому классу. То же самое не относится к интерфейсам, поскольку Java поддерживает наследование нескольких интерфейсов, но только одно наследование для классов. Таким образом, компилятор не может определить, реализует ли ссылочный тип определенный интерфейс или нет. Давайте приведем пример:

Мы получаем ClassCastException во второй строке вместо ошибки компиляции:

2.2. Литейные массивы

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

Таким образом, давайте посмотрим, что происходит с примитивными массивами, когда мы пытаемся выполнить следующее приведение:

Вторая строка вызывает исключение ClassCastException as autoboxing не работает для массивов.

Как насчет продвижения по службе? Давайте попробуем следующее:

Мы также получаем исключение ClassCastException , потому что продвижение типа не работает для целых массивов.

2.3. Безопасное литье

В случае явного приведения настоятельно рекомендуется проверить совместимость типов перед попыткой приведения с помощью instanceof .

Давайте рассмотрим пример безопасного приведения:

3. Загрязнение Кучи

В соответствии со спецификацией Java : ” Загрязнение кучи может произойти только в том случае, если программа выполнила какую-либо операцию с использованием необработанного типа, которая приведет к появлению непроверенного предупреждения во время компиляции”.

Для нашего эксперимента рассмотрим следующий универсальный класс:

Теперь мы попытаемся загрязнить кучу следующим образом:

Последняя строка вызовет исключение ClassCastException , поскольку она не может преобразовать ссылку D ouble в Long .

4. Общие типы

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

Давайте рассмотрим следующий общий метод:

А теперь давайте назовем это:

На первый взгляд, мы можем разумно ожидать нулевую ссылку, возвращаемую из блока catch. Однако во время выполнения из-за стирания типа параметр приводится к Object вместо String . Таким образом , компилятор сталкивается с задачей присвоения целого числа | строке , которая вызывает исключение ClassCastException.

5. Заключение

В этой статье мы рассмотрели ряд распространенных сценариев неподходящего кастинга.

Независимо от того, явные или неявные, приведение ссылок Java к другому типу может привести к ClassCastException , если целевой тип не совпадает или не является потомком фактического типа .

Код, используемый в этой статье, можно найти на GitHub .

Источник

Handling the ClassCastException Runtime Exception in Java

Table of Contents

Introduction to Runtime Exceptions

Runtime exceptions are exceptions which can not be checked at compile time. In Java, there are a myriad of classes derived from the RuntimeException class [1], all of which represent unchecked exceptions that need to be carefully considered and managed. Despite being less serious and critical than the unchecked runtime errors [2], these exceptions can still be very problematic and cause unexpected issues at runtime, especially if necessary precautions aren’t taken and relevant exception handling mechanisms aren’t put in place.

What is ClassCastException and When does it Happen?

As its name implies, ClassCastException is an exception that happens when the JVM tries to cast an object to a class (or in some instances, an interface) and fails. This relates to explicit type casting [3] and the reason the cast fails can be traced to an attempt at downcasting an object to a class of which it is not an instance, or to an interface which it does not implement.

ClassCastException is a subclass of the RuntimeException class which means it is an unchecked, runtime exception [4]. This exception can not be checked at compile-time because the compiler has no way of knowing whether the object is actually an instance of the target subclass, or if it is an instance of a subclass that implements the target interface. Consequently, if either of these scenarios is encountered at runtime, Java will throw the ClassCastException exception.

The only scenario where the compiler is able to detect invalid type casts of this kind is when the source type is a final class and it neither extends nor implements the target type, because it is known in advance that the final class does not have any subtypes, i.e., it cannot be subclassed [5].

How to handle ClassCastException

To prevent the ClassCastException exception, one should be careful when casting objects to a specific class or interface and ensure that the target type is a child of the source type, and that the actual object is an instance of that type. To help achieve type safety and catch these issues at compile time, two builtin Java mechanisms are available:

  1. the instanceof operator, and
  2. Generics.

ClassCastException Examples

To better understand ClassCastException , consider the following Java class hierarchy:

The resulting scenarios can be summarized as follows:

  • It is possible to cast an instance of X , Y , or Z , to Object , since all Java classes implicitly inherit the java.lang.Object class [6].
  • It is possible to cast an instance of Y or Z to X , because they are both subtypes of X .
  • It is possible to cast an instance of type X to type Y (or Z ) ONLY if the original object is of type Y (or Z ), due to polymorphism [7].
  • It is impossible to cast an instance of Y to Z despite the fact that they are both derived from X , because Y and Z are unique types with distinct states and behaviors.

Complete examples and ways to deal with ClassCastException are presented below.

Using the instanceof operator

Java’s instanceof operator is a binary operator used to test whether the object is an instance of a specific class, or a class that implements a specific interface [8]. When used in the appropriate context, this operator can prevent the ClassCastException exception from occurring. The code example below shows how trying to cast an instance of Phone to a subclass of Phone ( Smartphone ) throws the ClassCastException exception.

Casting an object to an interface is also a valid polymorphic operation, so one might try to cast the myPhone variable to a Wireless instance instead. However, since myPhone is not an instance of any class that implements Wireless , the ClassCastException is thrown again.

The solution here is to use the instanceOf operator which will enforce a safe type cast, as shown below.

The same concept applies to interfaces:

Since myPhone is neither an instance of Smartphone nor an instance of a class that implements Wireless , the instanceOf operator inside the if statement evaluates to false, and the corresponding else clause is executed.

On the other hand, if an object passes the instanceOf check, then it can be safely cast to the specified type. This can be observed in the example below where the myPhone variable is an actual instance of the Smartphone class (as initialized on line 16).

As a side note, older versions of Java which don’t support pattern matching for the instanceOf operator [9] will require an extra step to cast the object manually, as follows:

Using Generics & Parameterized Types

Introduced in Java 5, Generics are a very important addition to Java’s type system which brought compile-time type safety and eliminated the need for the tedious type casting when working with the Collections Framework [10]. This mechanism allows programmers to implement generic data structures and algorithms that are type-safe, and it allows Java compilers to perform strong type checking and detect related issues at compile-time.

A parameterized type is an instantiation of a generic type with an actual type argument. The code below shows how the use of raw, unparameterized collections such as List s can easily lead to the ClassCastException being triggered. This is because unparameterized collections default to the Object type, so nothing prevents a program or an API from inserting an instance of an unexpected type into a collection. The example below shows how inserting and later trying to cast the string “200” into a List instance throws the ClassCastException exception.

Using Generics to make the List parameterized restricts the types of objects the list can hold to valid instances of Integer , which in turn makes any attempt to insert any other, incompatible type in the list detectable at compile-time, as shown in the revised example below.

Furthermore, using parameterized types to instantiate Generics eliminates the need to cast collection objects manually, so a working version of the example above could look something like this:

Conclusion

Runtime exceptions are an inevitable evil that all Java programmers have to face at some point. One of these exceptions is the ClassCastException which is thrown whenever there is an attempt to cast an object to a class or an interface the object is incompatible with. As with other runtime exceptions, being prudent is important and pays off in the long run. This article explains what causes the ClassCastException by diving into Java’s type casting rules, and it shows how to prevent and effectively deal with this exception by relying on the instanceof operator and using generic, parameterized types when the situation calls for it.

Track, Analyze and Manage Errors With Rollbar

Managing Java errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

Источник

Java cast fail exception

short to byte or char

char to byte or short

int to byte , short , or char

long to byte , short , char , or int

float to byte , short , char , int , or long

double to byte , short , char , int , long , or float

A narrowing primitive conversion may lose information about the overall magnitude of a numeric value and may also lose precision and range.

A narrowing primitive conversion from double to float is governed by the IEEE 754 rounding rules (§4.2.4). This conversion can lose precision, but also lose range, resulting in a float zero from a nonzero double and a float infinity from a finite double . A double NaN is converted to a float NaN and a double infinity is converted to the same-signed float infinity.

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T . In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

A narrowing conversion of a char to an integral type T likewise simply discards all but the n lowest order bits, where n is the number of bits used to represent type T . In addition to a possible loss of information about the magnitude of the numeric value, this may cause the resulting value to be a negative number, even though chars represent 16-bit unsigned integer values.

A narrowing conversion of a floating-point number to an integral type T takes two steps:

In the first step, the floating-point number is converted either to a long , if T is long , or to an int , if T is byte , short , char , or int , as follows:

READ  There was an error completing your request please try again later

If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0 .

Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V , rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:

If T is long , and this integer value can be represented as a long , then the result of the first step is the long value V .

Otherwise, if this integer value can be represented as an int , then the result of the first step is the int value V .

Otherwise, one of the following two cases must be true:

The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int or long .

The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long .

In the second step:

If T is int or long , the result of the conversion is the result of the first step.

If T is byte , char , or short , the result of the conversion is the result of a narrowing conversion to type T (§5.1.3) of the result of the first step.

Example 5.1.3-1. Narrowing Primitive Conversion

This program produces the output:

The results for char , int , and long are unsurprising, producing the minimum and maximum representable values of the type.

The results for byte and short lose information about the sign and magnitude of the numeric values and also lose precision. The results can be understood by examining the low order bits of the minimum and maximum int . The minimum int is, in hexadecimal, 0x80000000 , and the maximum int is 0x7fffffff . This explains the short results, which are the low 16 bits of these values, namely, 0x0000 and 0xffff ; it explains the char results, which also are the low 16 bits of these values, namely, ‘\u0000’ and ‘\uffff’ ; and it explains the byte results, which are the low 8 bits of these values, namely, 0x00 and 0xff .

Despite the fact that overflow, underflow, or other loss of information may occur, a narrowing primitive conversion never results in a run-time exception (§11.1.1).

Example 5.1.3-2. Narrowing Primitive Conversions that lose information

This program produces the output:

5.1.4. Widening and Narrowing Primitive Conversion

The following conversion combines both widening and narrowing primitive conversions:

First, the byte is converted to an int via widening primitive conversion (§5.1.2), and then the resulting int is converted to a char by narrowing primitive conversion (§5.1.3).

5.1.5. Widening Reference Conversion

A widening reference conversion exists from any reference type S to any reference type T , provided S is a subtype (§4.10) of T .

Widening reference conversions never require a special action at run time and therefore never throw an exception at run time. They consist simply in regarding a reference as having some other type in a manner that can be proved correct at compile time.

5.1.6. Narrowing Reference Conversion

Six kinds of conversions are called the narrowing reference conversions :

From any reference type S to any reference type T , provided that S is a proper supertype of T (§4.10).

An important special case is that there is a narrowing reference conversion from the class type Object to any other reference type (§4.12.4).

From any class type C to any non-parameterized interface type K , provided that C is not final and does not implement K .

From any interface type J to any non-parameterized class type C that is not final .

From any interface type J to any non-parameterized interface type K , provided that J is not a subinterface of K .

From the interface types Cloneable and java.io.Serializable to any array type T [] .

From any array type SC [] to any array type TC [] , provided that SC and TC are reference types and there is a narrowing reference conversion from SC to TC .

Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If not, then a ClassCastException is thrown.

5.1.7. Boxing Conversion

Boxing conversion converts expressions of primitive type to corresponding expressions of reference type. Specifically, the following nine conversions are called the boxing conversions :

From type boolean to type Boolean

From type byte to type Byte

From type short to type Short

From type char to type Character

From type int to type Integer

From type long to type Long

From type float to type Float

From type double to type Double

From the null type to the null type

This rule is necessary because the conditional operator (§15.25) applies boxing conversion to the types of its operands, and uses the result in further calculations.

At run time, boxing conversion proceeds as follows:

If p is a value of type boolean , then boxing conversion converts p into a reference r of class and type Boolean , such that r .booleanValue() == p

If p is a value of type byte , then boxing conversion converts p into a reference r of class and type Byte , such that r .byteValue() == p

If p is a value of type char , then boxing conversion converts p into a reference r of class and type Character , such that r .charValue() == p

If p is a value of type short , then boxing conversion converts p into a reference r of class and type Short , such that r .shortValue() == p

If p is a value of type int , then boxing conversion converts p into a reference r of class and type Integer , such that r .intValue() == p

If p is a value of type long , then boxing conversion converts p into a reference r of class and type Long , such that r .longValue() == p

If p is a value of type float then:

If p is not NaN, then boxing conversion converts p into a reference r of class and type Float , such that r .floatValue() evaluates to p

Otherwise, boxing conversion converts p into a reference r of class and type Float such that r .isNaN() evaluates to true

If p is a value of type double , then:

If p is not NaN, boxing conversion converts p into a reference r of class and type Double , such that r .doubleValue() evaluates to p

Otherwise, boxing conversion converts p into a reference r of class and type Double such that r .isNaN() evaluates to true

If p is a value of any other type, boxing conversion is equivalent to an identity conversion (§5.1.1).

If the value p being boxed is true , false , a byte , or a char in the range \u0000 to \u007f , or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p . It is always the case that r1 == r2 .

Ideally, boxing a given primitive value p , would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer’s part. This would allow (but not require) sharing of some or all of these references.

This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.

A boxing conversion may result in an OutOfMemoryError if a new instance of one of the wrapper classes ( Boolean , Byte , Character , Short , Integer , Long , Float , or Double ) needs to be allocated and insufficient storage is available.

5.1.8. Unboxing Conversion

Unboxing conversion converts expressions of reference type to corresponding expressions of primitive type. Specifically, the following eight conversions are called the unboxing conversions :

From type Boolean to type boolean

From type Byte to type byte

From type Short to type short

From type Character to type char

From type Integer to type int

From type Long to type long

From type Float to type float

From type Double to type double

At run time, unboxing conversion proceeds as follows:

If r is a reference of type Boolean , then unboxing conversion converts r into r .booleanValue()

If r is a reference of type Byte , then unboxing conversion converts r into r .byteValue()

If r is a reference of type Character , then unboxing conversion converts r into r .charValue()

If r is a reference of type Short , then unboxing conversion converts r into r .shortValue()

If r is a reference of type Integer , then unboxing conversion converts r into r .intValue()

If r is a reference of type Long , then unboxing conversion converts r into r .longValue()

If r is a reference of type Float , unboxing conversion converts r into r .floatValue()

If r is a reference of type Double , then unboxing conversion converts r into r .doubleValue()

If r is null , unboxing conversion throws a NullPointerException

A type is said to be convertible to a numeric type if it is a numeric type (§4.2), or it is a reference type that may be converted to a numeric type by unboxing conversion.

A type is said to be convertible to an integral type if it is an integral type, or it is a reference type that may be converted to an integral type by unboxing conversion.

5.1.9. Unchecked Conversion

Let G name a generic type declaration with n type parameters.

There is an unchecked conversion from the raw class or interface type (§4.8) G to any parameterized type of the form G T1 . Tn > .

There is an unchecked conversion from the raw array type G [] to any array type type of the form G T1 . Tn > [] .

Use of an unchecked conversion causes a compile-time unchecked warning unless G . > is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1), or the unchecked warning is suppressed by the SuppressWarnings annotation (§9.6.3.5).

Unchecked conversion is used to enable a smooth interoperation of legacy code, written before the introduction of generic types, with libraries that have undergone a conversion to use genericity (a process we call generification). In such circumstances (most notably, clients of the Collections Framework in java.util ), legacy code uses raw types (e.g. Collection instead of Collection ). Expressions of raw types are passed as arguments to library methods that use parameterized versions of those same types as the types of their corresponding formal parameters.

Such calls cannot be shown to be statically safe under the type system using generics. Rejecting such calls would invalidate large bodies of existing code, and prevent them from using newer versions of the libraries. This in turn, would discourage library vendors from taking advantage of genericity. To prevent such an unwelcome turn of events, a raw type may be converted to an arbitrary invocation of the generic type declaration to which the raw type refers. While the conversion is unsound, it is tolerated as a concession to practicality. An unchecked warning is issued in such cases.

5.1.10. Capture Conversion

Let G name a generic type declaration (§8.1.2, §9.1.2) with n type parameters A1 . An with corresponding bounds U1 . Un .

There exists a capture conversion from a parameterized type G T1 . Tn > (§4.5) to a parameterized type G S1 . Sn > , where, for 1 ≤ in :

If Ti is a wildcard type argument (§4.5.1) of the form ? , then Si is a fresh type variable whose upper bound is Ui [ A1 := S1 . An := Sn ] and whose lower bound is the null type (§4.1).

If Ti is a wildcard type argument of the form ? extends Bi , then Si is a fresh type variable whose upper bound is glb( Bi , Ui [ A1 := S1 . An := Sn ] ) and whose lower bound is the null type.

It is a compile-time error if, for any two classes (not interfaces) Vi and Vj , Vi is not a subclass of Vj or vice versa.

If Ti is a wildcard type argument of the form ? super Bi , then Si is a fresh type variable whose upper bound is Ui [ A1 := S1 . An := Sn ] and whose lower bound is Bi .

Capture conversion on any type other than a parameterized type (§4.5) acts as an identity conversion (§5.1.1).

Capture conversion is not applied recursively.

Capture conversion never requires a special action at run time and therefore never throws an exception at run time.

Capture conversion is designed to make wildcards more useful. To understand the motivation, let’s begin by looking at the method java.util.Collections.reverse() :

The method reverses the list provided as a parameter. It works for any type of list, and so the use of the wildcard type List as the type of the formal parameter is entirely appropriate.

Now consider how one would implement reverse() :

The implementation needs to copy the list, extract elements from the copy, and insert them into the original. To do this in a type-safe manner, we need to give a name, T , to the element type of the incoming list. We do this in the private service method rev() . This requires us to pass the incoming argument list, of type List , as an argument to rev() . In general, List is a list of unknown type. It is not a subtype of List , for any type T . Allowing such a subtype relation would be unsound. Given the method:

the following code would undermine the type system:

So, without some special dispensation, we can see that the call from reverse() to rev() would be disallowed. If this were the case, the author of reverse() would be forced to write its signature as:

This is undesirable, as it exposes implementation information to the caller. Worse, the designer of an API might reason that the signature using a wildcard is what the callers of the API require, and only later realize that a type safe implementation was precluded.

The call from reverse() to rev() is in fact harmless, but it cannot be justified on the basis of a general subtyping relation between List and List . The call is harmless, because the incoming argument is doubtless a list of some type (albeit an unknown one). If we can capture this unknown type in a type variable X , we can infer T to be X . That is the essence of capture conversion. The specification of course must cope with complications, like non-trivial (and possibly recursively defined) upper or lower bounds, the presence of multiple arguments etc.

Mathematically sophisticated readers will want to relate capture conversion to established type theory. Readers unfamiliar with type theory can skip this discussion — or else study a suitable text, such as Types and Programming Languages by Benjamin Pierce, and then revisit this section.

Here then is a brief summary of the relationship of capture conversion to established type theoretical notions. Wildcard types are a restricted form of existential types. Capture conversion corresponds loosely to an opening of a value of existential type. A capture conversion of an expression e can be thought of as an open of e in a scope that comprises the top level expression that encloses e .

READ  Network related or instance specific error occurred while establishing

The classical open operation on existentials requires that the captured type variable must not escape the opened expression. The open that corresponds to capture conversion is always on a scope sufficiently large that the captured type variable can never be visible outside that scope. The advantage of this scheme is that there is no need for a close operation, as defined in the paper On Variance-Based Subtyping for Parametric Types by Atsushi Igarashi and Mirko Viroli, in the proceedings of the 16th European Conference on Object Oriented Programming (ECOOP 2002). For a formal account of wildcards, see Wild FJ by Mads Torgersen, Erik Ernst and Christian Plesner Hansen, in the 12th workshop on Foundations of Object Oriented Programming (FOOL 2005).

5.1.11. String Conversion

Any type may be converted to type String by string conversion .

A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression (§15.9):

If T is boolean , then use new Boolean( x ) .

If T is char , then use new Character( x ) .

If T is byte , short , or int , then use new Integer( x ) .

If T is long , then use new Long( x ) .

If T is float , then use new Float( x ) .

If T is double , then use new Double( x ) .

This reference value is then converted to type String by string conversion.

Now only reference values need to be considered:

If the reference is null , it is converted to the string » null » (four ASCII characters n , u , l , l ).

Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null , then the string » null » is used instead.

The toString method is defined by the primordial class Object (§4.3.2). Many classes override it, notably Boolean , Character , Integer , Long , Float , Double , and String .

See §5.4 for details of the string conversion context.

5.1.12. Forbidden Conversions

Any conversion that is not explicitly allowed is forbidden.

5.1.13. Value Set Conversion

Value set conversion is the process of mapping a floating-point value from one value set to another without changing its type.

Within an expression that is not FP-strict (§15.4), value set conversion provides choices to an implementation of the Java programming language:

If the value is an element of the float-extended-exponent value set, then the implementation may, at its option, map the value to the nearest element of the float value set. This conversion may result in overflow (in which case the value is replaced by an infinity of the same sign) or underflow (in which case the value may lose precision because it is replaced by a denormalized number or zero of the same sign).

If the value is an element of the double-extended-exponent value set, then the implementation may, at its option, map the value to the nearest element of the double value set. This conversion may result in overflow (in which case the value is replaced by an infinity of the same sign) or underflow (in which case the value may lose precision because it is replaced by a denormalized number or zero of the same sign).

Within an FP-strict expression (§15.4), value set conversion does not provide any choices; every implementation must behave in the same way:

If the value is of type float and is not an element of the float value set, then the implementation must map the value to the nearest element of the float value set. This conversion may result in overflow or underflow.

If the value is of type double and is not an element of the double value set, then the implementation must map the value to the nearest element of the double value set. This conversion may result in overflow or underflow.

Within an FP-strict expression, mapping values from the float-extended-exponent value set or double-extended-exponent value set is necessary only when a method is invoked whose declaration is not FP-strict and the implementation has chosen to represent the result of the method invocation as an element of an extended-exponent value set.

Whether in FP-strict code or code that is not FP-strict, value set conversion always leaves unchanged any value whose type is neither float nor double .

5.2. Assignment Conversion

Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable.

Assignment contexts allow the use of one of the following:

an identity conversion (§5.1.1)

a widening primitive conversion (§5.1.2)

a widening reference conversion (§5.1.5)

a boxing conversion (§5.1.7) optionally followed by a widening reference conversion

an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

If, after the conversions listed above have been applied, the resulting type is a raw type (§4.8), unchecked conversion (§5.1.9) may then be applied.

It is a compile-time error if the chain of conversions contains two parameterized types that are not in the subtype relation.

An example of such an illegal chain would be:

The first three elements of the chain are related by widening reference conversion, while the last entry is derived from its predecessor by unchecked conversion. However, this is not a valid assignment conversion, because the chain contains two parameterized types, Comparable and Comparable , that are not subtypes.

In addition, 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.

A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:

Byte and the value of the constant expression is representable in the type byte .

Short and the value of the constant expression is representable in the type short .

Character and the value of the constant expression is representable in the type char .

The compile-time narrowing of constants means that code such as:

is allowed. Without the narrowing, the fact that the integer literal 42 has type int would mean that a cast to byte would be required:

A value of the null type (the null reference is the only such value) may be assigned to any reference type, resulting in a null reference of that type.

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

If the type of an expression can be converted to the type of a variable by assignment conversion, we say the expression (or its value) is assignable to the variable or, equivalently, that the type of the expression is assignment compatible with the type of the variable.

If the type of the variable is float or double , then value set conversion (§5.1.13) is applied to the value v that is the result of the type conversion:

If v is of type float and is an element of the float-extended-exponent value set, then the implementation must map v to the nearest element of the float value set. This conversion may result in overflow or underflow.

If v is of type double and is an element of the double-extended-exponent value set, then the implementation must map v to the nearest element of the double value set. This conversion may result in overflow or underflow.

The only exceptions that an assignment conversion may cause are:

A ClassCastException if, after the type conversions above have been applied, the resulting value is an object which is not an instance of a subclass or subinterface of the erasure (§4.6) of the type of the variable.

This circumstance can only arise as a result of heap pollution (§4.12.2). In practice, implementations need only perform casts when accessing a field or method of an object of parametized type, when the erased type of the field, or the erased result type of the method differ from their unerased type.

An OutOfMemoryError as a result of a boxing conversion.

A NullPointerException as a result of an unboxing conversion on a null reference.

An ArrayStoreException in special cases involving array elements or field access (§10.5, §15.26.1).

Example 5.2-1. Assignment Conversion for Primitive Types

This program produces the output:

The following program, however, produces compile-time errors:

because not all short values are char values, and neither are all char values short values.

Example 5.2-2. Assignment Conversion for Reference Types

The following test program illustrates assignment conversions on reference values, but fails to compile, as described in its comments. This example should be compared to the preceding one.

Example 5.2-3. Assignment Conversion for Array Types

In this example:

The value of veclong cannot be assigned to a Long variable, because Long is a class type other than Object . An array can be assigned only to a variable of a compatible array type, or to a variable of type Object , Cloneable or java.io.Serializable .

The value of veclong cannot be assigned to vecshort , because they are arrays of primitive type, and short and long are not the same primitive type.

The value of cpvec can be assigned to pvec , because any reference that could be the value of an expression of type ColoredPoint can be the value of a variable of type Point . The subsequent assignment of the new Point to a component of pvec then would throw an ArrayStoreException (if the program were otherwise corrected so that it could be compiled), because a ColoredPoint array cannot have an instance of Point as the value of a component.

The value of pvec cannot be assigned to cpvec , because not every reference that could be the value of an expression of type ColoredPoint can correctly be the value of a variable of type Point . If the value of pvec at run time were a reference to an instance of Point[] , and the assignment to cpvec were allowed, a simple reference to a component of cpvec , say, cpvec[0] , could return a Point , and a Point is not a ColoredPoint . Thus to allow such an assignment would allow a violation of the type system. A cast may be used (§5.5, §15.16) to ensure that pvec references a ColoredPoint[] :

5.3. Method Invocation Conversion

Method invocation conversion is applied to each argument value in a method or constructor invocation (§8.8.7.1, §15.9, §15.12): the type of the argument expression must be converted to the type of the corresponding parameter.

Method invocation contexts allow the use of one of the following:

an identity conversion (§5.1.1)

a widening primitive conversion (§5.1.2)

a widening reference conversion (§5.1.5)

a boxing conversion (§5.1.7) optionally followed by widening reference conversion

an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

If, after the conversions listed above have been applied, the resulting type is a raw type (§4.8), an unchecked conversion (§5.1.9) may then be applied.

It is a compile-time error if the chain of conversions contains two parameterized types that are not in the subtype relation.

A value of the null type (the null reference is the only such value) may be converted to any reference type.

If the type of the expression cannot be converted to the type of the parameter by a conversion permitted in a method invocation context, then a compile-time error occurs.

If the type of an argument expression is either float or double , then value set conversion (§5.1.13) is applied after the type conversion:

If an argument value of type float is an element of the float-extended-exponent value set, then the implementation must map the value to the nearest element of the float value set. This conversion may result in overflow or underflow.

If an argument value of type double is an element of the double-extended-exponent value set, then the implementation must map the value to the nearest element of the double value set. This conversion may result in overflow or underflow.

The only exceptions that an method invocation conversion may cause are:

A ClassCastException if, after the type conversions above have been applied, the resulting value is an object which is not an instance of a subclass or subinterface of the erasure (§4.6) of the corresponding formal parameter type.

This circumstance can only arise as a result of heap pollution (§4.12.2).

An OutOfMemoryError as a result of a boxing conversion.

A NullPointerException as a result of an unboxing conversion on a null reference.

Method invocation conversions specifically do not include the implicit narrowing of integer constants which is part of assignment conversion (§5.2). The designers of the Java programming language felt that including these implicit narrowing conversions would add additional complexity to the overloaded method matching resolution process (§15.12.2).

Thus, the program:

causes a compile-time error because the integer literals 12 and 2 have type int , so neither method m matches under the rules of (§15.12.2). A language that included implicit narrowing of integer constants would need additional rules to resolve cases like this example.

5.4. String Conversion

String conversion applies only to an operand of the binary + operator which is not a String when the other operand is a String .

In this single special case, the non- String operand to the + is converted to a String (§5.1.11) and evaluation of the + operator proceeds as specified in §15.18.1.

5.5. Casting Conversion

Casting conversion is applied to the operand of a cast operator (§15.16): the type of the operand expression must be converted to the type explicitly named by the cast operator.

Casting contexts allow the use of one of:

an identity conversion (§5.1.1)

a widening primitive conversion (§5.1.2)

a narrowing primitive conversion (§5.1.3)

a widening and narrowing primitive conversion (§5.1.4)

a widening reference conversion (§5.1.5) optionally followed by either an unboxing conversion (§5.1.8) or an unchecked conversion (§5.1.9)

a narrowing reference conversion (§5.1.6) optionally followed by either an unboxing conversion (§5.1.8) or an unchecked conversion (§5.1.9)

a boxing conversion (§5.1.7) optionally followed by a widening reference conversion (§5.1.5)

an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion (§5.1.2).

Value set conversion (§5.1.13) is applied after the type conversion.

The compile-time legality of a casting conversion is as follows:

An expression of a primitive type may undergo casting conversion to another primitive type, by an identity conversion (if the types are the same), or by a widening primitive conversion, or by a narrowing primitive conversion, or by a widening and narrowing primitive conversion.

An expression of a primitive type may undergo casting conversion to a reference type without error, by boxing conversion.

An expression of a reference type may undergo casting conversion to a primitive type without error, by unboxing conversion.

An expression of a reference type may undergo casting conversion to another reference type if no compile-time error occurs given the rules in §5.5.1.

READ  Tls negotiation failed with error invalidtoken

The following tables enumerate which conversions are used in certain casting conversions. Each conversion is signified by a symbol:

— signifies no casting conversion allowed

≈ signifies identity conversion (§5.1.1)

ω signifies widening primitive conversion (§5.1.2)

η signifies narrowing primitive conversion (§5.1.3)

ωη signifies widening and narrowing primitive conversion (§5.1.4)

⇑ signifies widening reference conversion (§5.1.5)

⇓ signifies narrowing reference conversion (§5.1.6)

⊡ signifies boxing conversion (§5.1.7)

⊔ signifies unboxing conversion (§5.1.8)

In the tables, a comma between symbols indicates that a casting conversion uses one conversion followed by another. The type Object means any reference type other than the eight wrapper classes Boolean , Byte , Short , Character , Integer , Long , Float , Double .

Table 5.1. Casting conversions to primitive types

To → byte short char int long float double boolean
From ↓
byte ω ωη ω ω ω ω
short η η ω ω ω ω
char η η ω ω ω ω
int η η η ω ω ω
long η η η η ω ω
float η η η η η ω
double η η η η η η
boolean
Byte ⊔,ω ⊔,ω ⊔,ω ⊔,ω ⊔,ω
Short ⊔,ω ⊔,ω ⊔,ω ⊔,ω
Character ⊔,ω ⊔,ω ⊔,ω ⊔,ω
Integer ⊔,ω ⊔,ω ⊔,ω
Long ⊔,ω ⊔,ω
Float ⊔,ω
Double
Boolean
Object ⇓,⊔ ⇓,⊔ ⇓,⊔ ⇓,⊔ ⇓,⊔ ⇓,⊔ ⇓,⊔ ⇓,⊔

Table 5.2. Casting conversions to reference types

To → Byte Short Character Integer Long Float Double Boolean Object
From ↓
byte ⊡,⇑
short ⊡,⇑
char ⊡,⇑
int ⊡,⇑
long ⊡,⇑
float ⊡,⇑
double ⊡,⇑
boolean ⊡,⇑
Byte
Short
Character
Integer
Long
Float
Double
Boolean
Object

5.5.1. Reference Type Casting

Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules.

If S is a class type:

If T is a class type, then either | S | | T |, or | T | | S |. Otherwise, a compile-time error occurs.

Furthermore, if there exists a supertype X of T , and a supertype Y of S , such that both X and Y are provably distinct parameterized types (§4.5), and that the erasures of X and Y are the same, a compile-time error occurs.

If T is an interface type:

If S is not a final class (§8.1.1), then, if there exists a supertype X of T , and a supertype Y of S , such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.

Otherwise, the cast is always legal at compile time (because even if S does not implement T , a subclass of S might).

If S is a final class (§8.1.1), then S must implement T , or a compile-time error occurs.

If T is a type variable, then this algorithm is applied recursively, using the upper bound of T in place of T .

If T is an array type, then S must be the class Object , or a compile-time error occurs.

If S is an interface type:

If T is an array type, then S must be the type java.io.Serializable or Cloneable (the only interfaces implemented by arrays), or a compile-time error occurs.

If T is a type that is not final (§8.1.1), then if there exists a supertype X of T , and a supertype Y of S , such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.

Otherwise, the cast is always legal at compile time (because even if T does not implement S , a subclass of T might).

If T is a type that is final , then:

If S is not a parameterized type or a raw type, then T must implement S , or a compile-time error occurs.

Otherwise, S is either a parameterized type that is an invocation of some generic type declaration G , or a raw type corresponding to a generic type declaration G . Then there must exist a supertype X of T , such that X is an invocation of G , or a compile-time error occurs.

Furthermore, if S and X are provably distinct parameterized types then a compile-time error occurs.

If S is a type variable, then this algorithm is applied recursively, using the upper bound of S in place of S .

If S is an intersection type A1 & . & An , then it is a compile-time error if there exists an Ai (1 ≤ in ) such that S cannot be cast to Ai by this algorithm. That is, the success of the cast is determined by the most restrictive component of the intersection type.

If S is an array type SC [] , that is, an array of components of type SC :

If T is a class type, then if T is not Object , then a compile-time error occurs (because Object is the only class type to which arrays can be assigned).

If T is an interface type, then a compile-time error occurs unless T is the type java.io.Serializable or the type Cloneable (the only interfaces implemented by arrays).

If T is a type variable, then:

If the upper bound of T is Object or java.io.Serializable or Cloneable , or a type variable that S could undergo casting conversion to, then the cast is legal (though unchecked).

If the upper bound of T is an array type TC [] , then a compile-time error occurs unless the type SC [] can undergo casting conversion to TC [] .

Otherwise, a compile-time error occurs.

If T is an array type TC [] , that is, an array of components of type TC , then a compile-time error occurs unless one of the following is true:

TC and SC are the same primitive type.

TC and SC are reference types and type SC can undergo casting conversion to TC .

Example 5.5.1-1. Casting Conversion for Reference Types

Here, the first compile-time error occurs because the class types Long and Point are unrelated (that is, they are not the same, and neither is a subclass of the other), so a cast between them will always fail.

The second compile-time error occurs because a variable of type EndPoint can never reference a value that implements the interface Colorable . This is because EndPoint is a final type, and a variable of a final type always holds a value of the same run-time type as its compile-time type. Therefore, the run-time type of variable e must be exactly the type EndPoint , and type EndPoint does not implement Colorable .

Example 5.5.1-2. Casting Conversion for Array Types

This program compiles without errors and produces the output:

5.5.2. Checked Casts and Unchecked Casts

A cast from a type S to a type T is statically known to be correct if and only if S T (§4.10).

A cast from a type S to a parameterized type (§4.5) T is unchecked unless at least one of the following conditions holds:

All of the type arguments (§4.5.1) of T are unbounded wildcards

T S and S has no subtype X other than T where the type arguments of X are not contained in the type arguments of T .

A cast from a type S to a type variable T is unchecked unless S T .

An unchecked cast from S to T is completely unchecked if the cast from | S | to | T | is statically known to be correct. Otherwise, it is partially unchecked .

An unchecked cast causes a compile-time unchecked warning, unless suppressed by the SuppressWarnings annotation (§9.6.3.5).

A cast is checked if it is not statically known to be correct and it is not unchecked.

If a cast to a reference type is not a compile-time error, there are several cases:

The cast is statically known to be correct.

No run-time action is performed for such a cast.

The cast is a completely unchecked cast.

No run-time action is performed for such a cast.

The cast is a partially unchecked cast.

Such a cast requires a run-time validity check. The check is performed as if the cast had been a checked cast between | S | and | T |, as described below.

The cast is a checked cast.

Such a cast requires a run-time validity check. If the value at run time is null , then the cast is allowed. Otherwise, let R be the class of the object referred to by the run-time reference value, and let T be the erasure (§4.6) of the type named in the cast operator. A cast conversion must check, at run time, that the class R is assignment compatible with the type T , via the algorithm in §5.5.3.

Note that R cannot be an interface when these rules are first applied for any given cast, but R may be an interface if the rules are applied recursively because the run-time reference value may refer to an array whose element type is an interface type.

5.5.3. Checked Casts at Run Time

Here is the algorithm to check whether the run-time type R of an object is assignment compatible with the type T which is the erasure (§4.6) of the type named in the cast operator. If a run-time exception is thrown, it is a ClassCastException .

If R is an ordinary class (not an array class):

If T is a class type, then R must be either the same class (§4.3.4) as T or a subclass of T , or a run-time exception is thrown.

If T is an interface type, then R must implement (§8.1.5) interface T , or a run-time exception is thrown.

If T is an array type, then a run-time exception is thrown.

If R is an interface:

If T is a class type, then T must be Object (§4.3.2), or a run-time exception is thrown.

If T is an interface type, then R must be either the same interface as T or a subinterface of T , or a run-time exception is thrown.

If T is an array type, then a run-time exception is thrown.

If R is a class representing an array type RC [] , that is, an array of components of type RC :

If T is a class type, then T must be Object (§4.3.2), or a run-time exception is thrown.

If T is an interface type, then a run-time exception is thrown unless T is the type java.io.Serializable or the type Cloneable (the only interfaces implemented by arrays).

This case could slip past the compile-time checking if, for example, a reference to an array were stored in a variable of type Object .

If T is an array type TC [] , that is, an array of components of type TC , then a run-time exception is thrown unless one of the following is true:

TC and RC are the same primitive type.

TC and RC are reference types and type RC can be cast to TC by a recursive application of these run-time rules for casting.

Example 5.5.3-1. Incompatible Types at Run Time

This program uses casts to compile, but it throws exceptions at run time, because the types are incompatible.

5.6. Numeric Promotions

Numeric promotion is applied to the operands of an arithmetic operator.

Numeric promotion contexts allow the use of:

an identity conversion (§5.1.1)

a widening primitive conversion (§5.1.2)

an unboxing conversion (§5.1.8)

Numeric promotions are used to convert the operands of a numeric operator to a common type so that an operation can be performed. The two kinds of numeric promotion are unary numeric promotion (§5.6.1) and binary numeric promotion (§5.6.2).

5.6.1. Unary Numeric Promotion

Some operators apply unary numeric promotion to a single operand, which must produce a value of a numeric type:

If the operand is of compile-time type Byte , Short , Character , or Integer , it is subjected to unboxing conversion (§5.1.8). The result is then promoted to a value of type int by a widening primitive conversion (§5.1.2) or an identity conversion (§5.1.1).

Otherwise, if the operand is of compile-time type Long , Float , or Double , it is subjected to unboxing conversion (§5.1.8).

Otherwise, if the operand is of compile-time type byte , short , or char , it is promoted to a value of type int by a widening primitive conversion (§5.1.2).

Otherwise, a unary numeric operand remains as is and is not converted.

In any case, value set conversion (§5.1.13) is then applied.

Unary numeric promotion is performed on expressions in the following situations:

Each dimension expression in an array creation expression (§15.10)

The index expression in an array access expression (§15.13)

The operand of a unary plus operator + (§15.15.3)

The operand of a unary minus operator — (§15.15.4)

The operand of a bitwise complement operator

Each operand, separately, of a shift operator >> , >>> , or (§15.19).

A long shift distance (right operand) does not promote the value being shifted (left operand) to long .

Example 5.6.1-1. Unary Numeric Promotion

This program produces the output:

5.6.2. Binary Numeric Promotion

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

If either operand is of type double , the other is converted to double .

Otherwise, if either operand is of type float , the other is converted to float .

Otherwise, if either operand is of type long , the other is converted to long .

Otherwise, both operands are converted to type int .

After the type conversion, if any, value set conversion (§5.1.13) is applied to each operand.

Binary numeric promotion is performed on the operands of certain operators:

The multiplicative operators * , / and % (§15.17)

The addition and subtraction operators for numeric types + and — (§15.18.2)

The numerical comparison operators , , > , and >= (, and >=»>§15.20.1)

The numerical equality operators == and != (§15.21.1)

The integer bitwise operators & , ^ , and | (§15.22.1)

In certain cases, the conditional operator ? : (§15.25)

Example 5.6.2-1. Binary Numeric Promotion

This program produces the output:

The example converts the ASCII character G to the ASCII control-G (BEL), by masking off all but the low 5 bits of the character. The 7 is the numeric value of this control character.

Источник

Smartadm.ru