Conversion and Casting
Both Java and Rust are statically-typed at compile time. Hence, after a variable is declared, assigning a value of a different type (unless it's implicitly convertible to the target type) to the variable is prohibited. There are several ways to convert types in Java that have an equivalent in Rust.
Implicit conversions
Implicit conversions exist in Java as well as in Rust (called type coercions). Consider the following example:
int intNumber = 1;
long longNumber = intNumber; // `int` is implicitly converted to `long`
Rust is much more restrictive with respect to which type coercions are allowed:
let int_number: i32 = 1;
let long_number: i64 = int_number; // error: expected `i64`, found `i32`
An example for a valid implicit conversion using subtyping is:
fn bar<'a>() {
let s: &'static str = "hi";
let t: &'a str = s;
}
See also:
Explicit conversions
If converting could cause a loss of information, Java requires explicit conversions using a casting expression:
double a = 1.2;
int b = (int) a;
Rust does not provide coercion between primitive types, but instead uses
explicit conversion using the as
keyword (casting).
Casting in Rust will not cause a panic.
let int_number: i32 = 1;
let long_number: i64 = int_number as _;
Custom conversion
In Rust, the standard library contains an abstraction for converting a value
into a different type, in form of the From
trait and its
reciprocal, Into
. When implementing From
for a type, a default
implementation for Into
is automatically provided (called blanket
implementation in Rust). The following example illustrates two of such type
conversions:
fn main() {
let my_id = MyId("id".into()); // `into()` is implemented automatically due to the `From<&str>` trait implementation for `String`.
println!("{}", String::from(my_id)); // This uses the `From<MyId>` implementation for `String`.
}
struct MyId(String);
impl From<MyId> for String {
fn from(MyId(value): MyId) -> Self {
value
}
}
See also: