20190608_浅谈go&java差异(三)
转载请注明出处https://www.cnblogs.com/funnyzpc/p/10990703.html
第三节内容概览
- 多线程通讯(线程安全类型 chan)
- struct(结构体) 与 对象实体类
- 异常(panic 与 throw)
- 数组切片(slice)、map集合
- 继承,实现,组合(extend&interface&abstract)
- 包引入及管理(import、dep、module、maven)
- 打包运行(run build)
- 对象(receiver)函数(略)
多线程通讯(线程安全类型 chan)
java 提供了具有线程安全的类型以避免线程问题,比如AtomicLong、AtomicArray、AtomicInteger等等,其中对于字符串类型则提供了
StringBuffer类型来操作字符串,如果多个线程操作同一个jdk的数据安全类型的需要手动添加synchronized或者Lock()来保证并发数据
的安全性
public class AtomIntegerTest {
private static final Logger LOG = LoggerFactory.getLogger(AtomIntegerTest.class);
private static AtomicInteger atomicInt = new AtomicInteger();
/*
private static AtomicLong atomicLong = new AtomicLong();
private static AtomicArray atomicArray = new AtomicArray(100);
private static AtomicBoolean atomicBoolean = new AtomicBoolean();
*/
@Test
public void process01(){
IntStream.range(0,100).parallel().forEach(i->{
atomicInt.addAndGet(i);
});
LOG.info("result : {}",atomicInt);
}
}
- go
go语言则提供来chan关键字来辅助多协程通讯,而且go相对于java来说,他的基本数据类型也具有数据安全特性,其解决的方式有点儿类似于
消息队列的形式。
func main() {
c := make(chan int)
go func() {
for i := 0; i <= 100; i = i + 1 {
c <- i
}
close(c)
}()
j := 0
// 这里会阻塞 直到循环执行完成
for i := range c {
j = j + i
//fmt.Println(i)
}
fmt.Println("result : ", j)
fmt.Println("Finished")
}
struct(结构体) 与 对象实体类
- java
其实这方面java与go是没法比较的,go偏向于过程,而java是强面向对象的,这里仅仅阐述下各自对于数据的处理的结构差异
在java中可以说一切皆为对象,任何时候需要调用对象里面的函数必须new一个(也即创建一个),但是对于静态的方法不需要new,但是静态方法
一定是存在于对象之中的。java的数据对象定义是固定的,默认需要给参数加上getter和setter方法以做隐藏处理
public class PersonEntity {
private String name;
private int age;
private boolean isAdult;
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;
}
public boolean isAdult() {
return isAdult;
}
public void setAdult(boolean adult) {
isAdult = adult;
}
}
- go
go 对于数据对象的处理就开放的多,比如可以使用interface{} 代替所有struct(结构体),比如他的参数赋值也可以省略
(需要根据参数的位置来确定),同时也可以定义label来映射序列化json字段或映射数据库字段等(这个在java中需要定义注解来实现)
func main() {
p1 := PersonEntity{"Lina", 27, true}
p2 := PersonEntity{name: "Steve", age: 15, isAdult: false}
fmt.Println("p1 : ", p1)
fmt.Println("p2 : ", p2)
}
type PersonEntity struct {
name string
age int8
isAdult bool
}
异常(panic 与 throw)
- go
在go中没有异常抛出的概念,不过在大多数情况下均将异常放入error中返回,手动判断及处理异常;如果有显性抛出并
处理的地方需要配合defer去处理,同时抛出的异常是在panic的参数中定义
func main() {
defer func() { // 必须要先声明defer,否则不能捕获到panic异常
fmt.Println("process 03")
if err := recover(); err != nil {
fmt.Println(err) // 这里的err其实就是panic传入的内容,55
}
fmt.Println("process 04")
}()
f()
}
func f() {
fmt.Println("process 01")
panic("error info")
fmt.Println("process 02")
}
- java
java在可能出现异常的地方均会在方法上声明抛出(但这并不代表未声明的函数就一定不会抛出异常了),
这个时候需要在业务逻辑中选择抛出或者抓取处理就任由用户选择了
public class ThrowExceptionTest {
private static final Logger LOG = LoggerFactory.getLogger(ThrowExceptionTest.class);
@Test
public void process01(){
String[] strArr = {"a","b"};
// 数组取值时越界可能会抛出异常
LOG.info("value : {}",strArr[3]);
}
@Test
public void process02()/*throws UnsupportedEncoding