Go与Java语法对比(二)
Go与Java语法对比(二)
数组
Java:在Java语言中,数组声明格式如下:
// 声明一个长度为5, 元素类型为int的数组
int[] nums = new int[5];
// 对数组第一个元素进行赋值
nums[0] = 1;
// 访问数组的第一个元素
int num = nums[0];
// 声明的同时初始化数组
int[] nums = new int[] {1, 2, 3, 4, 5};
// 声明并初始化数组可以使用以下简化的语法
int[] nums = {1, 2, 3, 4, 5};
// 获取数组的长度
int length = nums.length;
// 创建多维数组
int[][] matrix = new int[2][2];Go:在Go语言中,数组声明格式如下:
// 声明一个长度为5, 元素类型为int的数组
var nums [5]int
// 对数组第一个元素进行赋值
nums[0] = 1
// 访问数组的第一个元素
var num = nums[0]
// 声明的同时初始化数组
var nums = [5]int {1,2,3,4,5}
// 简洁写法
nums := [5]int {1,2,3,4,5}
// 数组的长度声明可以省略, 用 ... 代替, 编译器会自动计算长度
nums := [...]int {1,2,3,4,5}
// 获取数组的长度
length := len(nums)
// 创建多维数组
var matrix [2][2]int
// 和Java语言不同的是, Go语言中的数组是值类型, 不是引用类型
// 将数组赋值给一个新变量, 新变量会得到一个原始数组的副本, 对新变量的修改不会影响原始数组
nums2 := nums
nums2[0] = 2
// 此时会输出1
fmt.Println(nums[0])切片(Go独有)
Java语言和Go语言中的数组都是固定长度的,一旦声明后不能再修改数组长度,实际使用时不够灵活,所以Java中专门提供了集合来解决数组长度限制的问题。而在Go语言中,在数组之上还建立了一种方便、灵活且功能强大的包装——切片(Slice)。切片是一种动态数组的抽象,它提供了对底层数组的部分或全部连续元素的引用。切片相比于数组具有更灵活的长度和容量,并且支持动态增长。
// 切片是对数组中一段连续元素的引用
// 先创建一个长度为5的数组
numArr := [5]int {1,2,3,4,5}
// 创建引用数组索引2到4的切片, 切片nums的值为[3,4]
nums := numArr[2:4]
// 切片是对原数组的引用, 对切片的修改会反映到原数组中, 此时数组numArr变为[1,2,4,4,5]
nums[0] = 4
// 此时会输出4
fmt.Println(numArr[2])
// 也可以直接声明一个切片
var nums []int
// 声明的同时进行初始化切片
nums := []int {1,2,3,4,5}
// 切片除了有长度属性表示切片中的元素数外, 还有容量属性, 表示从切片索引开始的引用数组中的元素数
// 切片长度为2
length := len(nums)
// 切片是从引用数组索引2开始的, 所以容量是3
capacity := cap(nums)
// 还可以使用make([]T,len,cap)函数创建切片, 此时会为切片中的元素进行自动初始化, int类型的元素默认值为0, 此时切片中的内容为[0,0,0,0,0]
nums := make([]int, 5, 5)
// 容量可省略, 默认值为切片长度
nums := make([]int, 5)
// 使用append函数可以向切片末尾添加一个或多个元素, append函数会返回一个新的切片, 原始切片保持不变
// 此时新的切片变为[0,0,0,0,0,1]
nums = append(nums, 1)
// 可以一次添加多个元素, 此时新的切片变为[0,0,0,0,0,1,2,3,4,5]
nums = append(nums, 2, 3, 4, 5)
// 可以使用... 运算符将一个切片添加到另一个切片中
nums1 := []int{1,2}
nums2 := []int{3,4,5}
// 此时nums中元素为[1,2,3,4,5]
nums := append(nums1, nums2...)Map / map
Java:在Java语言中,Map是一个接口,使用时需要创建一个Map接口的实现类:
Map<String, String> map = new HashMap<>();
// 添加一个键值对
map.put("name", "张三");
// 根据键获取对应的值
String name = map.get("name");
// 判断键是否存在
boolean exist = map.containsKey("name");
// 删除一个键值对
map.remove("name");
// 获取map的长度
int length = map.size();Go:在Go语言中,map是一种内置的数据类型,直接通过map关键字进行声明和使用:
// map 的零值是 nil, 必须使用 make 函数初始化
m := make(map[string]string)
// 可以声明的同时进行初始化
m := map[string]string {"name": "张三"}
// 添加一个键值对
m["name"] = "张三"
// 根据键获取对应的值
name := m["name"]
// 判断键是否存在, 如果 exist 是 true 表示 key 存在
value, exist := m["name"]
// 删除一个键值对
delete(m, "name")
// 获取map的长度
length := len(m)指针(Go独有)
Go:在Go语言中,指针是一种特殊的数据类型,用于存储变量的内存地址。指针可以用于直接访问和修改变量的值,而不是通过变量本身进行操作:
// 声明一个整数变量和一个指向整数的指针
num := 10
var ptr *int = &num
// 此处会打印num变量的地址
fmt.Println(ptr)
// 解引用指针, 获取指针指向的值, 此处会输出10
fmt.Println(*ptr)
// 修改指针指向的值, 指向的num变量也会被修改
*ptr = 20
// 此处会输出20
fmt.Println(num)
// 使用new函数创建指针
anotherPtr := new(int)
*anotherPtr = 30
// 此处会输出30
fmt.Println(*anotherPtr)类 / 结构体
Java:在Java语言中,数据的封装是通过类来进行实现:
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// 使用无参构造器创建对象
Person person = new Person();
// 使用有参构造器创建对象
Person person = new Person("张三", 18);
// 访问对象的属性
int age = person.age;
// 调用对象的方法
person.setAge(20);
int age = person.getAge();Go:在Go语言中,数据的封装是通过结构体来进行实现:
type Person struct {
name string
age int
}
// Go语言中, 可以在func关键字和函数名中间加入接收器, 来为结构体绑定方法, 通过这种方式可以实现和Java语言中类相似的行为
func (person *Person) GetName() string {
return person.name
}
func (person *Person) SetName(name string) {
person.name = name
}
func (person *Person) GetAge() int {
return person.age
}
func (person *Person) SetAge(age int) {
person.age = age
}
// 创建结构体
person := Person{}
// 创建结构体并赋值
person := Person{"张三", 18}
// 赋值时可以指定名称, 这样属性赋值的顺序可以与结构体定义顺序不一致
person := Person{age: 18, name: "张三"}
// 访问结构体的属性
person.age = 20
age := person.age
// 创建指向结构体的指针
person := &Person{"张三", 18}
// 使用指针访问结构体的属性
age := (*person).age
// Go语言可以省略显式的解引用
age := person.age
// 访问绑定了结构体的方法
person.SetAge(20)
age := person.GetAge()接口
Java:在Java语言中,实现接口必须使用 implement 关键字,来显式地声明该类实现了接口:
// 定义一个接口
public interface Shape {
double getArea();
}
// 实现接口的类
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
// 使用接口
Shape shape = new Circle(5.0);
System.out.println("Area: " + shape.getArea());Go:在Go语言中,不要显示声明实现接口,如果一个类型定义了与接口中定义的所有方法相匹配的方法,那么该类型隐式地满足该接口。这种方式称为结构体的隐式实现:
// 定义一个接口
type Shape interface {
getArea() float64
}
// 实现接口的结构体
type Circle struct {
radius float64
}
func (c Circle) getArea() float64 {
return math.Pi * c.radius * c.radius
}
// 使用接口
var shape Shape = Circle{radius: 5.0}
fmt.Println("Area:", shape.getArea())异常 / 错误
Java:在Java语言中,异常处理通过try-catch-finally语句块来实现,可以使用try块来包含可能抛出异常的代码,然后使用catch块来捕获并处理异常,最后可以使用finally块来执行清理操作:
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
}
// 执行除法运算的函数
public static int divide(int dividend, int divisor) {
if (divisor == 0) {
// 抛出一个ArithmeticException异常,表示除数为零的错误
throw new ArithmeticException("Division by zero");
}
return dividend / divisor;
}Go:在Go语言中,错误处理通过返回值来实现,函数可以返回一个额外的错误值,通常是最后一个返回值,以指示函数是否成功执行。调用函数时,需要检查返回的错误值并采取相应的处理措施:
func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err.Error())
} else {
fmt.Println("Result:", result)
}
}
// 执行除法运算的函数
func divide(dividend, divisor int) (int, error) {
if divisor == 0 {
// 使用errors.New函数创建一个新的错误值,表示除数为零的错误
return 0, errors.New("Division by zero")
}
return dividend / divisor, nil
}函数式接口 /头等函数
Java:在Java语言中,方法不能直接当做参数传递给其他方法,不过Java可以定义一个函数式接口,其中只包含一个方法,然后可以使用匿名内部类 / Lambda表达式方式创建实例来表示函数,从而做到类似的效果:
// 定义一个函数式接口
@FunctionalInterface
public interface MathOperation {
int operate(int a, int b);
}
public static void main(String[] args) {
// 定义一个接口实例,使用Lambda表达式创建匿名函数
MathOperation add = (a, b) -> a + b;
MathOperation subtract = (a, b) -> a - b;
// 调用operate函数执行数学操作,并输出结果
System.out.println("Addition: " + operate(5, 3, add));
System.out.println("Subtraction: " + operate(5, 3, subtract));
}
// 执行数学操作的函数
public static int operate(int a, int b, MathOperation operation) {
// 调用接口实例的方法来执行函数
return operation.operate(a, b);
}Go:在Go语言中,函数被视为一等公民,可以像其他值(如整数、字符串等)一样被赋值给变量、作为参数传递给其他函数或从函数中返回:
// 定义一个函数
type MathOperation func(a, b int) int
func main() {
// 定义函数类型的变量,使用匿名函数赋值
add := func(a, b int) int {
return a + b
}
subtract := func(a, b int) int {
return a - b
}
// 调用operate函数执行数学操作,并输出结果
fmt.Println("Addition:", operate(5, 3, add))
fmt.Println("Subtraction:", operate(5, 3, subtract))
}
// 执行数学操作的函数
func operate(a, b int, operation MathOperation) int {
// 调用函数类型变量来执行函数
return operation(a, b)
}