20190608_浅谈go&java差异(三)
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差异(三)的更多相关文章
- 20190312_浅谈go&java差异(一)
多线程 java java中对于大量的比较耗时的任务多采用多线程对方式对任务进行处理,同时由于进程和线程 本身是通过宿主机OS进行管理的,当在cpu核数较少或线程分配不当 会导致多线程的效果不佳的事常 ...
- 20190312_浅谈go&java差异(二)
转载请注明出处:https://www.cnblogs.com/funnyzpc/p/10801474.html 第二节内容概览 循环(for.switch) 多值返回 defer & fin ...
- 浅谈通信网络(三)——TCP/IP协议
简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...
- 浅谈TCP IP协议栈(三)路由器简介
读完这个系列的第一篇浅谈TCP/IP协议栈(一)入门知识和第二篇浅谈TCP/IP协议栈(二)IP地址,在第一篇中,可能我对协议栈中这个栈的解释有问题,栈在数据结构中是一种先进后出的常见结构,而在整个T ...
- 浅谈用java解析xml文档(三)
接上一篇,本文介绍使用JDOM解析xml文档, 首先我们还是应该知道JDOM从何而来,是Breet Mclaughlin和Jason Hunter两大Java高手的创作成果,2000年初, JDOM作 ...
- 浅谈:java泛型与dao重用
在进入今天的主题之前,我们先理解一下什么是泛型: 泛型是java中一种类型,泛型是被参数化的类型. 类型-->class 参数化-->class类型可以是任意参数 泛型存在的意义:泛型可以 ...
- 浅谈用java解析xml文档(四)
继续接上一文,这一阵子因为公司项目加紧,导致最后一个解析xml文档的方式,还没有总结,下面总结使用dom4J解析xml. DOM4J(Document Object Model for Java) 使 ...
- 浅谈对java中锁的理解
在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...
- 浅谈对java中传参问题的理解
之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...
随机推荐
- oracle实例状态
oracle数据库实例启动过程分三个步骤,分别是启动实例,加载数据库,打开数据. 1.NOMOUNT模式:这种模式只会创建实例,不会打开任何的数据文件,用户要以sysdba的身份登录,才具有关闭和启动 ...
- acm模板总结
模板链接 字符串模板 KMP EXKMP Trie 可持久化Trie树+DFS序 01Trie Manacher 字符串哈希 2019上海网络赛G题 17 SA(后缀数组) 最大不重叠相似子串 求两 ...
- ZOJ-1709
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...
- ZOJ 3195 Design the city (LCA 模板题)
Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terribl ...
- 【CSS】305- [译] Web 使用 CSS Shapes 的艺术设计
%; %; %; %; 0, 0 100%, 100% 100%); %; %; % 0, 0 100%, 100% 100%); %; %; ) p:nth-of-type(1)::before { ...
- JMeter之SteppingShape
1.背景 其实是这样的,最近包括以前都有同事问过宝路一个问题:JMeter测试计划中涉及到梯度压测时,整个测试计划执行完毕,聚合报告看的是整体的结果啊!并不能直观看到每个梯度下的吞吐量的值(虽然可以通 ...
- Web基础了解版02-JavaScript
JavaScript 特性 ① 解释型语言.JavaScript是一种解释型的脚本语言,JavaScript是在程序的运行过程中逐行进行解释,不需要被编译为机器码再执行. ② 面向对象.JavaScr ...
- Js 与浮点数
同步发表在我的博客:jmingzi 当你学习一个知识点没有方向时,可以尝试以解决问题的角度来理解它. 例如这个知识点我们可以从以下问题开始: 你看的到 1 真的是整数 1 吗? 为什么0.1 + 0. ...
- 面试 3-5年Java开发后的感受
在上周,我密集面试了若干位Java后端的候选人,工作经验在3到5年间.我的标准其实不复杂:第一能干活,第二Java基础要好,第三最好熟悉些分布式框架,我相信其它公司招初级开发时,应该也照着这个标准来面 ...
- 【CHRIS RICHARDSON 微服务系列】微服务架构中的进程间通信-3
编者的话 |本文来自 Nginx 官方博客,是微服务系列文章的第三篇,在第一篇文章中介绍了微服务架构模式,与单体模式进行了比较,并且讨论了使用微服务架构的优缺点.第二篇描述了采用微服务架构的应用客户端 ...