I present a translation of an article by Evan Cameron , which can help Java developers better understand the differences and similarities between the two languages - the original is on the author’s site . Not considering myself an experienced Rust developer, I’m unlikely to be able to reasonably participate in possible discussions.
I would like to make changes to the blog and leave more sensitive topics to focus on them. Perhaps one of the most important topics that can be done in the Rust community is the training of new developers. I was thinking about the best approach to teaching Rust for those who are used to working with Java and help to master the language for a new project.
Java was a language that I studied at the university, so my experience with it is somewhat anachronistic and I have not made any real attempts to keep up with the language. When I last wrote Java, if you wanted to pass a function as an argument, you had to declare a new interface or wrap the function in Callable<T>
. Since then, Java has come a long way. These are added functions that have a clear effect from functional programming. I am talking about lambdas, Optional
types, etc. This article will not talk about how to write in Rust or that you need to throw away all your Java code. Java is a great language with real use cases. I want to make some comparisons of Java and Rust for a beginner Rust programmer.
Language motivation
First about the goals of each language. Java was created to solve many problems. It had to be "simple, object-oriented and modular" , it had to work in a virtual machine, be portable to different architectures and it had to have high performance. Rust's goals are to be “incredibly fast and memory efficient” , have a “rich type system, memory security, thread-safe”, generate good error messages and have a built-in package manager.
. Rust , , . , Rust , . , , , , ( ) , (embedded) . , Rust. Rust , , (dangling) .
, Rust ( wasm frontends yew ). , , , , ( ) . .
, , Java Rust :
; , , . , .
Rust . Rust enum
struct
. enum
— ( , ). enum
Java, , Java enum
, . enum
, , . , , Rust null
nil
. Rust, .
enum Option<T> {
None,
Some(T),
}
Option
, T
. T
, T
. Option
2 , None
(" ") , Some
T
. :
let a = Some("foo".to_string());
let b: Option<usize> = Some(1);
. , . , . , .
Rust enum
match
. , .
fn plus(a: Option<usize>) -> Option<usize> {
match a {
Some(v) => Some(v + 1),
None => None
}
}
, . match
. cheats.rs match
. if/else
.
Option
, - ( Some
) . , Option
, .
fn plus(a: Option<usize>) -> Option<usize> {
a.map(|v| v + 1)
}
|| {}
— . Rust - , , " " .
struct
— . , , , .
struct A {
field: usize
}
"" .
let a: (usize, usize) = (1, 1);
.
struct Foo<T> {
field: T
}
enum
struct
. , impl
. , Rust. struct
impl
, :
struct Thangs {
list: Vec<Thang>
}
struct Thang;
impl Thangs {
fn new() -> Self {
Self {
list: vec![]
}
}
fn add_thang(&mut self, thang: Thang) {
self.list.push(thang);
}
}
fn main() {
let mut thangs = Thangs::new();
thangs.add_thang(Thang);
}
Java, value.method()
" ". , &mut self
:
let mut thangs = Thangs::new();
Thangs::add_thang(&mut thangs, Thang);
, Rust . enum
struct
. Java - struct
impl
, "", ( , ). " Rust ", Java , . Java 14 "Records" () . , Java "", ( , Rust , sum product ). Java, - , , !
Rust . , . . :
struct Thing { field: usize }
fn main() {
let a = Thing { field: 1 };
}
- . , , Sized
. , . , ( main) .
Java, new
, , .
Box
( stdlib , Rc
, Arc
..). , , ? , , , , ( ). , , , , "" Box
, .
fn main () {
let a = Box::new(Thing { field: 1 });
}
, . , . , , a
a
. usize
, .
Box
. - Java,
trait Foo {}
struct Thing;
impl Foo for Thing {}
struct OtherThing;
impl Foo for OtherThing {}
fn main () {
let a: Vec<Box<dyn Foo>> = vec![Box::new(OtherThing), Box::new(Thing)];
}
trait
, . , . , . Rust , , , , .
, , . Rust — .
.
enum List<T> {
Nil,
Cons((T, List<T>))
}
. List<T>
Nil
, Cons
, . , , ?
?
error[E0072]: recursive type `List` has infinite size
--> src/lib.rs:7:1
|
7 | enum List<T> {
| ^^^^^^^^^^^^ recursive type has infinite size
8 | Nil,
9 | Cons((T, List<T>))
| ------------ recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
. help
. , , . , , , N-? , , ? , . .
, .
enum List<T> {
Nil,
Cons((T, Box<List<T>>))
}
. , . .
Java Rust, ( ) :
enum Shape {
Circle { radius: f32 },
Rectangle { width: f32, height: f32 },
}
area
() , , , :
impl Shape {
pub fn area(self) -> f32 {
match self {
Shape::Circle { radius } => std::f32::consts::PI * radius.powi(2),
Shape::Rectangle { width, height } => width * height,
}
}
}
Java . Rust pub
( ), ( ). , Rust reference.
. Java Shape
Circle
Rectangle
, area
. Rust Java, :
Shape
:
- Java:
Shape
- Rust:
Shape
, ( match
, )
Shape
:
- Java: ""
Shape
, , - Rust:
impl
' ' (expression problem). . enum
Rust / Java. , Rust match
enum
. : « , ?»
, .
trait Area {
fn area(self) -> f32;
}
struct Rectangle {
width: f32,
height: f32
}
struct Circle {
radius: f32
}
impl Area for Rectangle {
fn area(self) -> f32 {
self.width * self.height
}
}
impl Area for Circle {
fn area(self) -> f32 {
std::f32::consts::PI * self.radius.powi(2)
}
}
, Circle
Rectangle
, perimeter
, :
trait Perimeter {
fn perimeter(self) -> f32;
}
impl Perimeter for Rectangle {
fn perimeter(self) -> f32 {
2. * (self.width + self.height)
}
}
. , , "" " ".
fn do_something<T: Perimeter + Area>(shape: T) {
unimplemented!()
}
Rust . , , Java. , . Java , Rust . , . , , . Future
, Iterator
IntoIterator
for..in
, Index
[]
, Add
, Sub
, Mul
. , Add
Add
std.
pub trait Add<Rhs = Self> {
type Output;
fn add(self, rhs: Rhs) -> Self::Output;
}
Std Add
Rhs
, Self
, .. (1). « » Output
(2) add
, self
( self
) rhs
Rhs
( ) , Output
(3).
use std::ops::Add;
#[derive(Debug)]
struct Content<T> {
val: T,
}
impl<T> Add for Content<T>
where
T: Add,
{
type Output = Content<<T as Add>::Output>;
fn add(self, rhs: Content<T>) -> Self::Output {
Content {
val: self.val + rhs.val,
}
}
}
fn main() {
let a = Content { val: 2 };
let b = Content { val: 5 };
println!("{:?}", a + b);
}
Content
, T
(1). Add
, Content
Add
(2), , Content
Add
(3). , Output
Content
Output
T
, Add
(4). , , , . , , . , " " , Rust. , Rust , ( ), .
, Sized
, fn foo<T>(t: T) -> T
, T: Sized
. T: ?Sized
, T
. .
Java . OO Rust, Java. Java — (subtype polymorphism), Rust — (ad-hoc) . , , , ( <T: Trait>
).
, "" . , enum
struct
, impl
. impl
, . , , -. .
Rust . str
, String
, OsStr
, OsString
, CString
CStr
( - ?). , str
String
, — . , , ?
&str
, &str
&String
, String
Deref<Target=str>
( Target=
, Target
" "). .
fn foo<S: AsRef<str>>(s: S) {
unimplemented!()
}
AsRef
— stdlib. :
trait AsRef<T>
where
T: ?Sized,
{
fn as_ref(&self) -> &T;
}
, T, , &T
. foo
String
,
let a = String::from("stuff");
foo(a);
? , ( ). Rust stdlib.
, . , , . , . Java ( , Java ). Java , . « ». Rust , .
, , . , - . , , . Rust , ! , Rust .
.
: Java Rust
Java , . , . - Java , .. . , , Java , ( Java <T>
<T extends Class>
), Java , (type erasure). , Object
-. Java, , — . - vtable, .
Rust . foo
foo
, foo
. , foo
4 AsRef<str>
, 4 . «». , Rust " ". ( Box
), Object
or transfer a virtual table if we don’t want it. It should be noted that the disadvantage of this method is the final code size and compilation time. Depending on how many different variants of our functions and how many implementations we need to generate, the more code must go through LLVM, increasing compilation time and increasing the amount of actually generated code.
Contacts Evan Cameron: mail , github , twitter , linkedIn
A slow discussion of Rust translations takes place in a telegram chat for Rust translations .