AWS的clone是否影响在线aws服务器

搭建自己的ngrok服务
| Go语言中文网 | Golang中文社区 | Golang中国
<meta name="author" content="polaris ">
搭建自己的ngrok服务
搭建自己的ngrok服务
在国内开发、以及做前端开发的朋友想必对都不陌生吧,就目前来看,ngrok可是最佳的在内网调试微信服务的tunnel工 具。记得今年春节前,提供的服务还一切正常呢,但春节后似乎就一切不正常了。无法访问,ngrok虽然能连上 提供的服务,但微信端因为无法访问,导致消息一直无法发送到我们的服务地址上,比如。 这一切都表明,ngork被墙了。没有了ngrok tunnel,一切开始变得困难且没有效率起来。内网到外部主机部署和调试是一件慢的让人想骂街的事情。
ngrok不能少。ngrok以及其服务端ngrokd都是开源的,之前我也知道通过源码可以自搭建ngrok服务。请求搜索引擎后,发现国内有个朋友已经搭建了一个www.tunnel.mobi的ngrok公共服务,与类似,我也实验了一下。
编写一个ngrok.cfg,内容如下:
server_addr: "tunnel.mobi:44433"
trust_host_root_certs: true
用ngrok最新客户端1.7版本执行如下命令:
$ngrok -subdomain tonybaiexample -config=ngrok.cfg 80
可以顺利建立一个tunnel,用于本机向外部提供"tonybaiexample.tunnel.mobi"服务。
Tunnel Status
Forwarding
http://tonybaiexample.tunnel.mobi -> 127.0.0.1:80
Forwarding
https://tonybaiexample.tunnel.mobi -> 127.0.0.1:80
Web Interface
127.0.0.1:4040
Avg Conn Time
而且国内的ngrok服务显然要远远快于提供的服务,消息瞬间即达。
但这是在公网上直接访问的结果。放在公司内部,我看到的却是另外一个结果:
Tunnel Status
reconnecting
Web Interface
127.0.0.1:4040
Avg Conn Time
我们无法从内网建立tunnel,意味着依旧不方便和低效,因为很多基础服务都在内网部署,内外网之间的交互十分不便。但内网连不上tunnel.mobi也是个事实,且无法知道原因,因为看不到server端的连接错误日志。
于是我决定自建一个ngrok服务。
一、准备工作
搭建ngrok服务需要在公网有一台vps,去年年末曾经在Amazon申请了一个体验主机,有公网IP一个,这次就打算用这个主机作为ngrokd服务端。
需要一个自己的域名。已有域名的,可以建立一个子域名,用于关联ngrok服务,这样也不会干扰原先域名提供的服务。(不用域名的方式也许可以,但我没有试验过。)
搭建的参考资料主要来自下面三个:
1) ngrok的官方SELFHOST指南:/inconshreveable/ngrok/blob/master/docs/SELFHOSTING.md
2) 国外一哥们的博客:/2014/09/run-ngrok-on-your-own-server/
3) "海运的博客"中的一篇文章:http://www.haiyun.me/archives/1012.html
二、实操步骤
我的AWS EC2实例安装的是Server 14.04 x86_64,并安装了 1.4(go version go1.4 linux/amd64)。Golang是编译ngrokd和ngrok所必须的,建议直接从golang官方下载对应平台的二进制安装包(国内可以从 上下载,速度慢些罢了)。
1、下载ngrok源码
(GOPATH=~/goproj)
$ mkdir ~/goproj//inconshreveable
$ git clone /inconshreveable/ngrok.git
$ export GOPATH=~/goproj//inconshreveable/ngrok
2、生成自签名证书
使用官方服务时,我们使用的是官方的SSL证书。自建ngrokd服务,我们需要生成自己的证书,并提供携带该证书的ngrok客户端。
证书生成过程需要一个NGROK_BASE_DOMAIN。 以ngrok官方随机生成的地址为例,其NGROK_BASE_DOMAIN就是"",如果你要 提供服务的地址为"example.",那NGROK_BASE_DOMAIN就应该 是""。
我们这里以NGROK_BASE_DOMAIN=""为例,生成证书的命令如下:
$ cd ~/goproj//inconshreveable/ngrok
$ openssl genrsa -out rootCA.key 2048
$ openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=" -days 5000 -out rootCA.pem
$ openssl genrsa -out device.key 2048
$ openssl req -new -key device.key -subj "/CN=" -out device.csr
$ openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
执行完以上命令,在ngrok目录下就会新生成6个文件:
-rw-rw-r– 1 ubuntu ubuntu 1001 Mar 14 02:22 device.crt
-rw-rw-r– 1 ubuntu ubuntu
903 Mar 14 02:22 device.csr
-rw-rw-r– 1 ubuntu ubuntu 1679 Mar 14 02:22 device.key
-rw-rw-r– 1 ubuntu ubuntu 1679 Mar 14 02:21 rootCA.key
-rw-rw-r– 1 ubuntu ubuntu 1119 Mar 14 02:21 rootCA.pem
-rw-rw-r– 1 ubuntu ubuntu
17 Mar 14 02:22 rootCA.srl
ngrok通过bindata将ngrok源码目录下的assets目录(资源文件)打包到可执行文件(ngrokd和ngrok)中 去,assets/client/tls和assets/server/tls下分别存放着用于ngrok和ngrokd的默认证书文件,我们需要将它们替换成我们自己生成的:(因此这一步务必放在编译可执行文件之前)
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key
3、编译ngrokd和ngrok
在ngrok目录下执行如下命令,编译ngrokd:
$ make release-server
不过在我的AWS上,出现如下错误:
GOOS="" GOARCH="" go /jteeuwen/go-bindata/go-bindata
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/client/assets/assets_release.go \
assets/client/…
make: bin/go-bindata: Command not found
make: *** [client-assets] Error 127
go-bindata被安装到了$GOBIN下了,go编译器找不到了。修正方法是将$GOBIN/go-bindata拷贝到当前ngrok/bin下。
$ cp /home/ubuntu/.bin/go14/bin/go-bindata ./bin
再次执行make release-server。
make release-server
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/client/assets/assets_release.go \
assets/client/…
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/server/assets/assets_release.go \
assets/server/…
go get -tags 'release' -d -v ngrok/…
/p/log4go (download)
go: missing Mercurial command. See
package /p/log4go: exec: "hg": executable file not found in $PATH
/gorilla/websocket (download)
/inconshreveable/go-update (download)
/kardianos/osext (download)
/kr/binarydist (download)
/inconshreveable/go-vhost (download)
/inconshreveable/mousetrap (download)
/nsf/termbox-go (download)
/mattn/go-runewidth (download)
/rcrowley/go-metrics (download)
Parsing meta tags from
(status code 200)
get "gopkg.in/yaml.v1": found meta tag main.metaImport{Prefix:"gopkg.in/yaml.v1", VCS:"git", RepoRoot:} at
gopkg.in/yaml.v1 (download)
make: *** [deps] Error 1
又出错!提示找不到hg,原来是aws上没有安装hg。install hg后(sudo apt-get install mercurial),再编译。
$ make release-server
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/client/assets/assets_release.go \
assets/client/…
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/server/assets/assets_release.go \
assets/server/…
go get -tags 'release' -d -v ngrok/…
/p/log4go (download)
go install -tags 'release' ngrok/main/ngrokd
同样编译ngrok:
$ make release-client
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/client/assets/assets_release.go \
assets/client/…
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/server/assets/assets_release.go \
assets/server/…
go get -tags 'release' -d -v ngrok/…
go install -tags 'release' ngrok/main/ngrok
AWS上ngrokd和ngrok被安装到了$GOBIN下。
1、启动ngrokd
$ ngrokd -domain="" -httpAddr=":8080" -httpsAddr=":8081"
[03/14/15 04:47:24] [INFO] [registry] [tun] No affinity cache specified
[03/14/15 04:47:24] [INFO] [metrics] Reporting every 30 seconds
[03/14/15 04:47:24] [INFO] Listening for public http connections on [::]:8080
[03/14/15 04:47:24] [INFO] Listening for public https connections on [::]:8081
[03/14/15 04:47:24] [INFO] Listening for control and proxy connections on [::]:4443
2、公网连接ngrokd
将生成的ngrok下载到自己的电脑上。
创建一个配置文件ngrok.cfg,内容如下:
server_addr: ":4443"
trust_host_root_certs: false
执行ngrok:
$ ngrok -subdomain example -config=ngrok.cfg 80
Tunnel Status
reconnecting
Web Interface
127.0.0.1:4040
Avg Conn Time
连接失败。此刻我的电脑是在公网上。查看ngrokd的日志,没有发现连接到达Server端。试着在本地ping 这个地址,发现地址不通。难道是DNS设置的问题。之前我只是设置了"*."的A地址,并未设置""。于是到DNS管理页面,添加了""的A记录。
待DNS记录刷新OK后,再次启动ngrok:
Tunnel Status online
Version 1.7/1.7
Forwarding http://epower.:8080 -> 127.0.0.1:80
Forwarding https://epower.:8080 -> 127.0.0.1:80
Web Interface 127.0.0.1:4040
Avg Conn Time 0.00ms
这回连接成功了!
3、内网连接ngrokd
将ngrok拷贝到内网的一台PC上,这台PC设置了公司的代理。
按照同样的步骤启动ngrok:
$ ngrok -subdomain example -config=ngrok.cfg 80
Tunnel Status
reconnecting
Web Interface
127.0.0.1:4040
Avg Conn Time
不巧,怎么又失败了!从Server端来看,还是没有收到客户端的连接,显然是连接没有打通公司内网。从我自己的squid代理服务器来看,似乎只有443端口的请求被公司代理服务器允许通过,4443则无法出去。
.558 .126.101 TCP_MISS/000 366772 CONNECT api.equinox.io:443 – DEFAULT_PARENT/ -
.441 27 10.10.126.101 TCP_MISS/000 1185 CONNECT :4443 – DEFAULT_PARENT/ -
似乎没有通过
只能修改server监听端口了。将-tunnelAddr由4443改为443(注意AWS上需要修改防火墙的端口规则,这个是实时生效的,无需重启实例):
$ sudo ngrokd -domain="" -httpAddr=":8080" -httpsAddr=":8081" -tunnelAddr=":443"
[03/14/15 04:47:24] [INFO] [registry] [tun] No affinity cache specified
[03/14/15 04:47:24] [INFO] [metrics] Reporting every 30 seconds
[03/14/15 04:47:24] [INFO] Listening for public http connections on [::]:8080
[03/14/15 04:47:24] [INFO] Listening for public https connections on [::]:8081
[03/14/15 04:47:24] [INFO] Listening for control and proxy connections on [::]:443
将ngrok.cfg中的地址改为443:
server_addr: ":443"
再次执行ngrok客户端:
Tunnel Status
Forwarding
http://epower.:8080 -> 127.0.0.1:80
Forwarding
https://epower.:8080 -> 127.0.0.1:80
Web Interface
127.0.0.1:4040
Avg Conn Time
这回成功连上了。
是否大功告成了呢?我们看看ngrok的结果,总感觉哪里不对呢?噢,转发的地址怎么是8080端口呢?为何不是80?微信公众号/企业号可只是支持80端口啊!
我们还需要修改一下Server端的参数,将-httpAddr从8080改为80。
$ sudo ngrokd -domain="" -httpAddr=":80" -httpsAddr=":8081" -tunnelAddr=":443"
这回再用ngrok连接一下:
Tunnel Status
Forwarding
http://epower. -> 127.0.0.1:80
Forwarding
https://epower. -> 127.0.0.1:80
Web Interface
127.0.0.1:4040
Avg Conn Time
这回与我们的需求匹配上了。
在内网的PC上建立一个简单的http server 程序:hello
//hello.go
package main
import "net/http"
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":80", nil)
func hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello!"))
$ go build -o hello hello.go
$ sudo ./hello
通过公网浏览器访问一下“http://epower.”这个地址,如果你看到浏览器返回"hello!"字样,那么你的ngrokd服务就搭建成功了!
四、注意事项
客户端ngrok.cfg中server_addr后的值必须严格与-domain以及证书中的NGROK_BASE_DOMAIN相同,否则Server端就会出现如下错误日志:
[03/13/15 09:55:46] [INFO] [tun:15dd7522] New connection from 54.149.100.42:38252
[03/13/15 09:55:46] [DEBG] [tun:15dd7522] Waiting to read message
[03/13/15 09:55:46] [WARN] [tun:15dd7522] Failed to read message: remote error: bad certificate
[03/13/15 09:55:46] [DEBG] [tun:15dd7522] Closing
(C) 2015, . 版权所有.
支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
支持 @ 本站用户;支持表情(输入 : 提示),见
记住登录状态
还不是会员Git远程操作详解
发表于 16:21|
来源阮一峰的网络日志|
作者阮一峰
摘要:Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能。本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Git远程操作。
【编者按】Git是一个分布式版本控制/软件配置管理软件,原是Linux内核开发者林纳斯·托瓦兹(Linus Torvalds)为更好地管理Linux内核开发而设计。是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能。Git有很多优势,其中之一就是远程操作非常简便。本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Git远程操作。
git remote
本文针对初级用户,从最简单的讲起,但是需要读者对Git的基本用法有所了解。同时,本文覆盖了上面5个命令的几乎所有的常用用法,所以对于熟练用户也有参考价值。
一、git clone
远程操作的第一步,通常是从远程主机克隆一个版本库,这时就要用到git clone命令。$ git clone &版本库的网址&
比如,克隆jQuery的版本库。$ git clone &a href="/jquery/jquery.git"&/jquery/jquery.git&/a&
该命令会在本地主机生成一个目录,与远程主机的版本库同名。如果要指定不同的目录名,可以将目录名作为git clone 命令的第二个参数。$ git clone &版本库的网址& &本地目录名&
git clone 支持多种协议,除了 HTTP (s)以外,还支持 SSH、Git、本地文件协议等,下面是一些例子。$ git clone http[s]:///path/to/repo.git/
$ git clone ssh:///path/to/repo.git/
$ git clone git:///path/to/repo.git/
$ git clone /opt/git/project.git
$ git clone file:///opt/git/project.git
$ git clone ftp[s]:///path/to/repo.git/
$ git clone rsync:///path/to/repo.git/
SSH协议还有另一种写法。$ git clone [user@]:path/to/repo.git/
通常来说,Git协议下载速度最快,SSH协议用于需要用户认证的场合。各种协议优劣的详细讨论请参考。
二、git remote
为了便于管理,Git要求每个远程主机都必须指定一个主机名。git remote命令就用于管理主机名。
不带选项的时候,git remote命令列出所有远程主机。$ git remote
使用-v选项,可以参看远程主机的网址。$ git remote -v
:jquery/jquery.git (fetch)
:jquery/jquery.git (push)
上面命令表示,当前只有一台远程主机,叫origin,以及它的网址。
克隆版本库的时候,所使用的远程主机自动被Git命名为origin。如果想用其他的主机名,需要用git clone命令的-o选项指定。$ git clone -o jQuery &a href="/jquery/jquery.git"&/jquery/jquery.git&/a&
$ git remote
上面命令表示,克隆的时候,指定远程主机叫做jQuery。
git remote show 命令加上主机名,可以查看该主机的详细信息。$ git remote show &主机名&
git remote add 命令用于添加远程主机。$ git remote add &主机名& &网址&
git remote rm 命令用于删除远程主机。$ git remote rm &主机名&
git remote rename 命令用于远程主机的改名。$ git remote rename &原主机名& &新主机名&
三、git fetch
一旦远程主机的版本库有了更新(Git术语叫commit),需要将这些更新取回本地,这时就要用到git fetch命令。$ git fetch &远程主机名&
上面命令将某个远程主机的更新,全部取回本地。
默认情况下,git fetch 取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。$ git fetch &远程主机名& &分支名&
比如,取回 origin 主机的 master 分支。$ git fetch origin master
所取回的更新,在本地主机上要用"远程主机名/分支名"的形式读取。比如origin主机的master,就要用origin/master读取。
git branch命令的-r选项,可以用来查看远程分支,-a选项查看所有分支。$ git branch -r
origin/master
$ git branch -a
remotes/origin/master
上面命令表示,本地主机的当前分支是 master,远程分支是 origin/master。
取回远程主机的更新以后,可以在它的基础上,使用 git checkout 命令创建一个新的分支。$ git checkout -b newBrach origin/master
上面命令表示,在origin/master 的基础上,创建一个新分支。
此外,也可以使用git merge命令或者git rebase 命令,在本地分支上合并远程分支。$ git merge origin/master
$ git rebase origin/master
上面命令表示在当前分支上,合并origin/master。
四、git pull
git pull 命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。$ git pull &远程主机名& &远程分支名&:&本地分支名&
比如,取回 origin 主机的 next 分支,与本地的 master 分支合并,需要写成下面这样。$ git pull origin next:master
如果远程分支是与当前分支合并,则冒号后面的部分可以省略。$ git pull origin next
上面命令表示,取回 origin/next 分支,再与当前分支合并。实质上,这等同于先做git fetch,再做git merge。&$ git fetch origin
$ git merge origin/next
在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在 git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的
master 分支自动"追踪"origin/master分支。
Git也允许手动建立追踪关系。git branch --set-upstream master origin/next
上面命令指定 master 分支追踪 origin/next 分支。
如果当前分支与远程分支存在追踪关系,git pull 就可以省略远程分支名。$ git pull origin
上面命令表示,本地的当前分支自动与对应的 origin 主机"追踪分支"(remote-tracking branch)进行合并。
如果当前分支只有一个追踪分支,连远程主机名都可以省略。$ git pull
上面命令表示,当前分支自动与唯一一个追踪分支进行合并。
如果合并需要采用rebase模式,可以使用--rebase选项。$ git pull --rebase &远程主机名& &远程分支名&:&本地分支名&
五、git push
git push 命令用于将本地分支的更新,推送到远程主机。它的格式与git pull 命令相仿。$ git push &远程主机名& &本地分支名&:&远程分支名&
注意,分支推送顺序的写法是&来源地&:&目的地&,所以git pull是&远程分支&:&本地分支&,而git push是&本地分支&:&远程分支&。
如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。$ git push origin master
上面命令表示,将本地的 master 分支推送到 origin 主机的 master 分支。如果后者不存在,则会被新建。
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。$ git push origin :master
$ git push origin --delete master
上面命令表示删除origin主机的master分支。
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。$ git push origin
上面命令表示,将当前分支推送到origin主机的对应分支。
如果当前分支只有一个追踪分支,那么主机名都可以省略。$ git push
如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push。$ git push -u origin master
上面命令将本地的 master 分支推送到 origin 主机,同时指定 origin 为默认主机,后面就可以不加任何参数使用 git push
不带任何参数的 git push,默认只推送当前分支,这叫做 simple 方式。此外,还有一种 matching 方式,会推送所有有对应的远程分支的本地分支。Git
2.0 版本之前,默认采用 matching 方法,现在改为默认采用 simple 方式。如果要修改这个设置,可以采用 git config
命令。$ git config --global push.default matching
$ git config --global push.default simple
还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用--all选项。$ git push --all origin
上面命令表示,将所有本地分支都推送到origin主机。
如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用--force选项。$ git push --force origin
上面命令使用--force 选项,结果导致在远程主机产生一个"非直进式"的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用--force选项。
最后,git push 不会推送标签(tag),除非使用--tags选项。$ git push origin --tags原文出自:
推荐阅读相关主题:
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章966,690 十月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
AWS在线问答:为什么选择AWS?AWS有哪些认证与考试?
AWS在线问答:为什么选择AWS?AWS有哪些认证与考试?
ArchSummit全球架构师峰会(北京站)-03日举办,
Author Contacted
相关厂商内容
相关赞助商
更多AWS最新精彩内容和活动,!
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。java.util.ArrayList.clone是不是彻底的克隆?
java.util.ArrayList.clone()是不是连数组中的对象也克隆了?
java.util.ArrayList&MyType&&myarr=XXXX;
java.util.ArrayList&MyType&&myclone=(java.util.ArrayList&MyType&)myarr.clone();
MyType&t=myarr.get(1);
MyType&c=myclone.get(1);
1.c&和&t&引用的是不是不同的两个对象?对c的任何操作都不会影响到t?
2.MyType&是不是必须重载一个clone函数?
不是深克隆,所以
1.&是同一个对象
2.&重写不重写都没有区别
这算是什么。
String[]&a&=&{"aa","bb"};
String[]&b&=&Arrays.copyOf(a,a.length);
引用&1&楼&dollyn&的回复:不是深克隆,所以
1.&是同一个对象
2.&重写不重写都没有区别
任何彻底的深层克隆,基本上只能依赖序列化
明白了深克隆的定义。
&public&Object&clone()&{
&&&&&&&&try&{
&&&&&&&&&&&&@SuppressWarnings("unchecked")
&&&&&&&&&&&&&&&&ArrayList&E&&v&=&(ArrayList&E&)&super.clone();
&&&&&&&&&&&&v.elementData&=&Arrays.copyOf(elementData,&size);
&&&&&&&&&&&&v.modCount&=&0;
&&&&&&&&&&&&return&v;
&&&&&&&&}&catch&(CloneNotSupportedException&e)&{
&&&&&&&&&&&&//&this&shouldn't&happen,&since&we&are&Cloneable
&&&&&&&&&&&&throw&new&InternalError();
这2个是重新指过的
v.elementData&
&&&v.modCount&=&0;
引用&4&楼&u&的回复:明白了深克隆的定义。
&public&Object&clone()&{
&&&&&&&&try&{
&&&&&&&&&&&&@SuppressWarnings("unchecked")
&&&&&&&&&&&&&&&&ArrayList&E&&v&=&(ArrayList&E&)&super.clone();
&&&&&&&&&&&&v.elementData&=&Arrays.copyOf(elementData,&size);
&&&&&&&&&&&&v.modCount&=&0;
&&&&&&&&&&&&return&v;
&&&&&&&&}&catch&(CloneNotSupportedException&e)&{
&&&&&&&&&&&&//&this&shouldn't&happen,&since&we&are&Cloneable
&&&&&&&&&&&&throw&new&InternalError();
这2个是重新指过的
v.elementData&
&&&v.modCount&=&0;
是深层克隆
除elementData外,其他是primitive.
一个对象的深克隆,就是这个对象下面所有的引用类型,都重新克隆过。那数组举例
浅克隆就是你看到的Arrays.copyOf,&System.arraycopy,数组是新的,但是里面N个元素全是旧的
一般意义的深克隆,就是
A[]&newArray&=&new&A[oldArray.length];
for&(int&i&=&0;&i&=&newArray.&i++)&{
&&newArray[i]&=&(A)&oldArray[i].clone();
但是这个只是一般意义的,完全依赖于A类(及其所有字段所在的类)的clone方法,是否彻底
所以我前面说,序列化/反序列化,是一个比较彻底深克隆,当然,也有限制,要去都是可序列化的
浅克隆就是你看到的Arrays.copyOf,&System.arraycopy,数组是新的,但是里面N个元素全是旧的
newArray[0].x&=&"我是新的,肯定是新的了,因为我克隆过了!!!";&
oldArray[0].x&=&"图样图森破";
引用浅克隆就是你看到的Arrays.copyOf,&System.arraycopy
引用&3&楼&shine333&的回复:Quote: 引用&1&楼&dollyn&的回复:
不是深克隆,所以
1.&是同一个对象
2.&重写不重写都没有区别
任何彻底的深层克隆,基本上只能依赖序列化
说的都很好,不彻底
本来我以为是很彻底的克隆……
刚刚我验证了一下,太恶心了,要去重新修改代码。
谢谢大家。
明显不是一个对象,你用==试一下,卧槽,感觉整个讨论都是错的。
即使是一小步也想与你分享}

我要回帖

更多关于 aws云服务 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信