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

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 UnsupportedEncodingException*/{
String str = "hello";
byte[] enCodeArr = {};
try {
// getBytes 显式抛出异常了,需要抛出或者抓取(try catch)处理
enCodeArr = Base64.getEncoder().encode(str.getBytes("utf-8"));
}catch (UnsupportedEncodingException e){
LOG.error("异常 : ",e);
}
LOG.info("enCode result : {}",enCodeArr);
}
/*
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, value, 0, value.length);
}
*/
}

集合([ ]、slice、map、Array、Map)

  • java([ ]、Array、Map)

    java 的集合类型有三类:

    • [] : 且称它为定长单值数组

    • Array :可以理解是一个定长数组的管理器,它实现了不定长数组

      根据不同的算法有ArrayList、Set、TreeSet 等等

    • Map : 是一个键值对的集合类型,它的值可以是基本数据类型也可以是自定义数据类型

      它的实现也有很多 HashMap、TresMap、LinkedHashMap 等等

public class ArrayTest {
private static final Logger LOG = LoggerFactory.getLogger(ArrayTest.class); @Test
public void process01(){
// 这里定义了长度为4的定长数组,当取或放>4个值后会抛异常
String[] arrBase= new String[4];
arrBase[0] = "hello";
LOG.info("len {},{}",arrBase.length,arrBase[0]); // 这里定义了一个默认长度为4的不定长数组,当然是可以放入>4个值的
List<Integer> lst = new ArrayList<Integer>(4){{
add(0);
add(22);
add(-1);
}};
LOG.info("arr len {},{}",lst.size(),lst.toString());
} @Test
public void process02(){
// 这里定义了一个键值对集合
Map<String,Object> hashMap = new HashMap<String,Object>(2){{
put("a",1);
put("b",2);
}};
LOG.info("map len {},{}",hashMap.size(),hashMap.toString());
}
}
  • go([ ]、slice、map)

go的集合有三种形式,其中数组与切片数组看似相似,其实对于内存分配有很大差异,一般实际使用后者,同时需要说明的是map也可使用make关键字

做集合优化。

go 的集合类型有三类,目前均无多算法实现:

- 数组

- 切片数组(slice)

- 键值对集合(map)

func main() {
// 这里定义了一个不定长数组(这种描述可能不准确)
var arr []int8
arr = append(arr, 100)
arr = append(arr, -1)
fmt.Println(arr)
// 这里使用slice 定义了一个长度为3,容量为3的数组
arr2 := make([]string, 3, 3)
arr2 = append(arr2, "hello")
arr2[2] = "youth"
//arr2 = append(arr2, "youth")
// arr2 = append(arr2, "good")
// arr2 = append(arr2, "morning")
fmt.Println(cap(arr2), len(arr2), arr2)
}

继承,实现,组合(extend&interface&abstract)

  • java

java 有继承extend和实现interface 之分,一个类只能单继承或者多实现,但不管是被继承还是被实现,他们的类型还是有差异的

(访问类型也是有差异的)

public class ExtendIntfTest {

}

 interface EntityA{
void doSth01();
// private doSth02();
}
class EntityB{
public void doSth01(){ }
} public abstract class EntityC { public void doSth01(){
// TODO
} public void doSth02(){
// TODO
}
}
  • go

go更偏向于过程,只给出了组合作为继承的一种实现,而且是通过结构体嵌套实现的,不说了还是看代码吧:

package main

import (
"fmt"
) type Base struct {
} func (b *Base) ShowA() {
fmt.Println("showA")
}
func (b *Base) ShowB() {
fmt.Println("showB")
} type Derived struct {
Base
} func (d *Derived) ShowB() {
fmt.Println("Derived showB")
} func main() {
// 当 Derived 的结构体中包含Base时也就相当于继承了Base 的 ShowA() 方法
d := Derived{}
d.ShowA()
d.ShowB()
}

包引入及管理(import、dep、module、maven)

 go的包引入与java比较相似,均是通过在java文件或者go文件首行定义包名称以被引入,不过使用的细节上还有有丢丢
差异的,比如在go内如果有多个引入 则使用 import()来包含,同时还可以对引入做忽略(不够准确,与init相关)和别名处理
同时对于包(module模块)的管理在go 1.11之前多用dep,而在go 1.11及之后则引入来go module,个人觉得有点儿像git,对于多个
工程的管理更加的方便了。 java中如果存在同包内多个子包引入则在包尾使用*,同一package内引入不用声明引入,对于包的管理多用maven(以及gradle),但对于较老的
工程也有手动导入的方式。

打包运行(run build)

 go的打包只有官方标准的,每一个安装了go语言的机器都内置了go的一些列命令,包含 打包、构建、运行、测试、拉取依赖等等,不过
虽然方便但也有不足之处,比如`go run`命令没有提供进程守护,需要第三方实现;再比如 `go package` 的包比较大不利于发布,
一般使用upx命令缩减包的大小。
java的打包有官方和非官方两种,官方只定义了jar包的打包的规范,对于工程管理却没有提供任何工具;而非官方的以maven为主(还有gradle),不仅仅
可以管理依赖和工程结构等等~=,比官方好用多了~;而运行主要将打包后的文件扔进容器即可,同时容器提供了进程守护等功能,容器以tomcat、
jetty、webLogic、ws为主,均为非官方。

20190608_浅谈go&java差异(三)的更多相关文章

  1. 20190312_浅谈go&java差异(一)

    多线程 java java中对于大量的比较耗时的任务多采用多线程对方式对任务进行处理,同时由于进程和线程 本身是通过宿主机OS进行管理的,当在cpu核数较少或线程分配不当 会导致多线程的效果不佳的事常 ...

  2. 20190312_浅谈go&java差异(二)

    转载请注明出处:https://www.cnblogs.com/funnyzpc/p/10801474.html 第二节内容概览 循环(for.switch) 多值返回 defer & fin ...

  3. 浅谈通信网络(三)——TCP/IP协议

    简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...

  4. 浅谈TCP IP协议栈(三)路由器简介

    读完这个系列的第一篇浅谈TCP/IP协议栈(一)入门知识和第二篇浅谈TCP/IP协议栈(二)IP地址,在第一篇中,可能我对协议栈中这个栈的解释有问题,栈在数据结构中是一种先进后出的常见结构,而在整个T ...

  5. 浅谈用java解析xml文档(三)

    接上一篇,本文介绍使用JDOM解析xml文档, 首先我们还是应该知道JDOM从何而来,是Breet Mclaughlin和Jason Hunter两大Java高手的创作成果,2000年初, JDOM作 ...

  6. 浅谈:java泛型与dao重用

    在进入今天的主题之前,我们先理解一下什么是泛型: 泛型是java中一种类型,泛型是被参数化的类型. 类型-->class 参数化-->class类型可以是任意参数 泛型存在的意义:泛型可以 ...

  7. 浅谈用java解析xml文档(四)

    继续接上一文,这一阵子因为公司项目加紧,导致最后一个解析xml文档的方式,还没有总结,下面总结使用dom4J解析xml. DOM4J(Document Object Model for Java) 使 ...

  8. 浅谈对java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

  9. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

随机推荐

  1. [TimLinux] django context_processor介绍

    1. context django里面 render 函数,HttpResponse,都有一个参数,context={},这个参数用于将视图层处理得到的数据传递到模板层. 2. context_pro ...

  2. 【全栈修炼】396- OAuth2 修炼宝典

    一.OAuth 概念 开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用.-- 维基百科 ...

  3. 面试完腾讯,总结了这12道Zookeeper面试题!

    前言 ZooKeeper 是一个开源的分布式协调服务,可以基于 ZooKeeper 实现诸如:数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管理.Master 选举.配置维护,名字服务.分 ...

  4. pipelinedb学习笔记 - 1. Continuous Views (连续视图)

    Continuous Views 一.Continuous Views 英文直译过来叫连续视图, 在pipelindb中是被定义为专门用来展示 Stream中数据用的.例如:Stream中有一些用户信 ...

  5. WinForm GroupBox控件重绘外观

    private void groupBoxFun_Paint(PaintEventArgs e, GroupBox groupBox){ e.Graphics.Clear(groupBox.BackC ...

  6. uni-app开发小程序入门到崩溃

    最近一段时间公司要做一个小程序项目,还要支持,微信小程序,头条小程序,百度小程序.一套代码,实现三个平台.当时接到这个任务,就不知道怎么去下手,一套代码,分别要发布三个平台,赶紧就去上网了解这些东西, ...

  7. OpenWrite一款博客可一文多发的实用工具

    前言 许多网友想看一文多发的OpenWrite,今天,它来了!别问落地价,因为内测无价! 这款实用工具,可支持十大博客平台一键发布,是博主们的发文神器 你看它多种平台.一键管理.后台界面优雅.还有签到 ...

  8. WPF布局容器

    1.StackPanel:堆栈面板,通过Orientation属性设置子元素的布局排列方向为“Vertical”(垂直)和“Horizontal”(水平),不写其默认值为“Vertical”,当设置为 ...

  9. SAP B1:水晶报表中用Code128制作条型码的方法

    一.在[文件系统]中新建一个[Fonts文件夹],然后添加[Code128.ttf]文件. 二.在水晶报表里的[字段资源管理器]的[公式字段]中新建一个公式字段.点击[使用编辑器]之后弹出[公式工作室 ...

  10. Android 项目优化(七):阿里巴巴Android开发手册整理总结

    本来之前觉得Android项目优化系列的文章基本整理完毕了,但是近期看了一下<阿里Android开发手册>有了很多收获,想再整理一篇,下面就开始吧. 先在这里列一下之前整理的文章及链接: ...