0. Java Go区别 精简版:
0.1 语法
0.1.1 访问权限
Java使用public、protected、private、默认等几种修饰符来控制访问权限;
golang通过大小写控制包外可访问还是不可访问。
实际bug:gorm中定义对象结构体时全部变量名都需要大写,否则grom无法找到数据进行映射
0.1.2 异常处理
- java中错误(Error)和异常(Exception)被分类管理,二者的区别是:
-
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。
-
EXCEPTION(异常):
- 运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)
- 非运行时异常 (编译异常):IOException、SQLException等以及用户自定义的Exception异常
- golang中只有error,一旦发生错误逐层返回,直到被处理。Golang中引入两个内置函数panic和recover来触发和终止异常处理流程,同时引入关键字defer来延迟执行defer后面的函数。golang弱化了异常,只有错误,在意料之外的panic发生时,在defer中通过recover捕获这个恐慌,转化为错误以code,message的形式返回给方法调用者,调用者去处理,这也是go极简的精髓;
0.2 面向对象
-
继承:
Java的继承通过extends关键字完成,不支持多继承;Go中没有显式的继承,可以使用组合方式实现继承;从该层面讲支持多继承;
-
封装
-
多态:
java的多态,必须满足继承,重写,向上转型;任何用户定义的类型都可以实现任何接口,所以通过不同实体类型对接口值方法的调用就是多态。
在Go语言中通过接口实现多态,对接口的实现只需要某个类型T实现了接口中的方法,就相当于实现了该接口。所有的类都默认实现了空接口;
-
接口:
java等面向对象编程的接口是侵入式接口,需要明确声明自己实现了某个接口。
Golang的非侵入式接口不需要通过任何关键字声明类型与接口之间的实现关系,只要一个类型实现了接口的所有方法,那么这个类型就是这个接口的实现类型。
0.3 性能
0.3.1 编译部署
-
Java通过虚拟机编译,使用JVM跨平台编译;
-
Go中不存在虚拟机,针对不同的平台,编译对应的机器码
0.3.2 并发
- Java中,通常借助于共享内存(全局变量)作为线程间通信的媒介,通常会有线程不安全问题,使用了加锁(同步化)、使用原子类、使用volatile提升可见性等解决;
- Golang中使用的是通道(channel)作为协程间通信的媒介,这也是Golang中强调的:不要通过共享内存通信,而通过通信来共享内存。golang使用GMP并发模型,多个goroutine之间通过Channel来通信,chan的读取和写入操作为原子操作,所以是安全的。
0.3.3 垃圾回收与内存管理
-
Java基于JVM虚拟机的分代收集算法完成GC;
-
golang内存释放是语言层面,对不再使用的内存资源进行自动回收,使用多级缓存,非分代,并发的三色标记算法。
一下文章转载自 丰巢技术团队 - 各有千秋:浅谈Go和Java的语法特性对比
Go和Java作为在世界上影响巨大的两门开发语言,在语言特点和应用领域上都存在共通和相似之处。Go从2009年开源至今,在docker、K8s、企业后台等领域都取得了非凡的影响。本文以Golang的主要feature为研究对象,共分为6个章节,在学习这些特性的同时,给出其在Java中对应的实现方式,并会详细分析其中的原理和差异。
1. 接口
在面向对象语言中,接口是一个绕不开的话题和特性,我们首先通过一段代码来看一下Go中的接口是如何设计和使用的:
在代码中定义了两个结构体:Teacher和Student;
定义了一个接口:Person,接口中声明了一个方法:notice();
在Teacher和Student中都存在notice()方法的实现,并且方法签名与Person中的notice()一致;
main包中的全局函数sendMsg(p Person) ,通过输入参数为Person的接口,来调用实现Person接口的notice方法;
函数sendMsg(p Person),是一个通过接口实现的多态应用;
1.1 Go中实现接口
package main
import "fmt"
type Teacher struct {
Name string
}
type Student struct {
Name string
}
type Person interface {
notice()
}
func (t Teacher) notice() {
fmt.Println(t.Name, "hello")
}
func (s Student) notice() {
fmt.Println(s.Name, "hello")
}
//sendMsg接收一个实现了Person接口的struct
func sendMsg(p Person) {
p.notice()
}
func main() {
t := Teacher{
"Teacher Liu"}
s := Student{
"Student Li"}
sendMsg(t)
sendMsg(s)
}
1.2 Java实现接口
Java的实现代码
-
Java中至少需要3个文件来实现;
-
Java使用interface关键字来定义接口;
-
Java在类中使用implements关键字来显式的实现接口;
-
Java中的方法是定义在Class里面的;
Person.java中定义Person接口代码
public interface Person {
public void notice();
}
Teacher.java中定义Teacher类
public class Teacher implements Person{
public String name;
public Teacher(String name){
this.name = name;
}
@Override
public void notice() {
System.out.println(name+" hello");
}
}
Student.java中定义Student类和main方法等
public class Student implements Person{
public String name;
public Student(String name){
this.name = name;
}
@Override
public void notice() {
System.out.println(name+" hello");
}
public static void sendMsg(Person p){
p.notice();
}
public static void main(String[] args