问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

JAVA如何阅读代码更高效?

发布网友 发布时间:2022-04-19 01:15

我来回答

6个回答

懂视网 时间:2022-04-19 05:37

最近在看Twitter的Oauth2的库的源代码(simplegeo/python-oauth2 · GitHub),看不进去啊...整个库有些自成体系的感觉,看上去联系很紧密,所以从哪里开始看都不方便。从上往下看代码的话,肯定会被各种函数看晕。从main()开始看的话,也会被好多层的调用搞晕。因为之前对Python的Http请求的库并不熟悉(如httplib2, requests),经常会需要看一下其它库的一些内容,更晕了...

现在总是觉得自己明白大致的流程,但总有大段的函数看不懂,结合文档看也总有很多地方不明白。自己就是想看明白一些,然后对这个库做一些改进(因为有些API的Oauth流程和其它API的有区别,所以我想改进一下Oauth的过程)。但现在的理解程度,完全达不到这个要求啊...(这两天找到了一个新的库,可以满足我的要求,但我还是想搞明白怎么读代码比较好...)

各位资深的程序员们,我应该怎么做才好呢...

回复内容:

先看文档,再看单元测试。 Code Reading (豆瓣) (副题是 The Open Source Perspective,适合题主需求)
代码阅读 (豆瓣) (中译本) 之前也是读代码很慢,后来代码写的多了读这些开源项目的速度就明显快了。
读代码慢就是对常用函数和常用库不熟,不熟悉python常用的编程技巧,读代码的时候精力太分散,读代码是一句一句的读,还需要经常上网查语法什么的,没有办法把精力放在代码的整体结构上,即使是每行代码都看明白了还是不知道整个程序的逻辑,同时耗费精力比较大,很快就累了,效率很低。
熟悉了常用库和编程技巧之后读代码的时候很多功能自己都实现过类似的,扫一眼就看明白了,很多函数扫一眼就知道什么功能,思路不会被不懂得语法或者编程技巧打断,一直停留在程序的逻辑上,这样看代码就轻松多了,而且很快,基本上小的项目随便翻翻就知道它的思路了,大的项目的话其实不用全都把握,只要把与自己要看的部分相关的熟悉了就好了。
读代码快的人也并不是什么都会比你快,当他们碰到一些没见过的东西时也是需要查询,自己写一些例子来熟悉,也要花一些时间,熟悉单个知识点也并不比你快。
文档和测试用例对于楼主目前的阶段来说用处不大,这些东西只能是在你读代码变快了以后锦上添花的东西,很多时候看看文档和测试用例会加快理解这个库的速度,起个和代码对照的作用
如果想要通过熟悉这个库来提高编程水平的话,就把里面用到的第三方库和编程技巧自己多写写,这样回过头来看就知道作者为什么这么写了,很多代码看起来很复杂其实思路很简单的。 一开始我也觉得是自己没有掌握方法,一度还想去买一本很著名的教人读代码的书,后来没买,因为不知不觉我就发现我读代码越来越容易了。
你觉得调用栈跳来跳去的记不住是吧?你觉得模块功能联系太多反馈回路太复杂是吧?其实真正原因是你脑子不够用!
一开始,我读一个三四千行的代码要做上千字的笔记看上一俩星期,后来就不用了,读下来函数调用栈都在脑子里,最多画个草图标一下各模块依赖关系。后来有一次给新人讲模块,用SI,函数间点来点去点得飞快,最后发现我这一口气已经走了几十个函数了。
计算机跑程序,调用栈太多会耗尽内存死机,人读代码,大脑的调用栈太多就会耗尽记忆力然后晕掉,解决办法就是多读代码,把你大脑能够支持更深的调用栈深度的记忆力的潜力开发出来。等突破临界点了你自然会懂怎么读。 先骂作者,然后找个小点的例子调试。 多看,猛看,看了几十万行规模的系统后再看其他系统就自然如履平地。

原文地址:Aaron Liu - Welcome to my blog! ? 阅读源代码的几个步骤

需要技能:程序调试能力.

1,跑通程序.

2,运行程序的核心功能,从外部了解它的运行方式.

3,阅读核心功能相关的官方文档.

4,读核心功能对应的源代码(即核心模块)和单元测试,从内部大概了解一下核心模块之间的联系.

5,提出一个关于源码的问题(比如状态机如何运作,filters分为几层等),试图解决.

6,浏览该问题相关代码和测试,然后边调试边解决问题,(不要在代码非常不熟悉的情况下就开始调试,过长的程序栈会消耗太多时间).

7,继续提出问题,直至核心模块烂熟于心.

8,(可选)与同学同事交流学习该模块,或写成博客与网友分享,以加深记忆,获取反馈.这次你很有可能会发现理解上的漏洞或错误,进行查漏补缺吧.

9,开始阅读次核心模块,并重复3-7步骤.

10,如果还嫌不足,为该程序开发插件或库吧.

11,理解源码.
详情请查看我的PPT:如何阅读源代码.pptx_免费高速下载

问题导向阅读代码的方法分为外部和内部两个部分.

外部阅读:带着问题去看,自己提出一个程序常用的应用场景,然后自己去在程序上测试一些主要逻辑,比如后台添加了A,前台是否就生成了B?服务端修改了C,客户端会不会出现D之类.  

内部阅读:带着问题去看,提出一个如何写程序拓展的场景,(你以后想拓展这一块逻辑该怎么做?有没有内建的现成API可供调用),总之不要被文档带着思路走,要被问题带着思路走.

请大家多拍砖或补充,多谢.

这方面有好几本专门的书和文章,也有朋友提供了具体的、系统性的技巧,就不重复了。
还是从个人角度来建议,不求全面,主要是两点:
  1. 从弄清楚目标开始,逐层理解目标系统的设计思路到最后如何实现的具体细节;
  2. 如果有能力,甚至换位思考:与其说是阅读别人的代码,不如说是自己再设计实现一遍——那你是不是也是从弄清楚目标开始,然后提出解决思路,进一步得到解决方案,再分解成若干模块......逐层分解下去?那这样的话还会吃力么?
主要技巧大概说几个关键词吧:
  1. 自顶向下:从目标代码实现的功能、解决的问题(需求),逐层分解问题/解决问题的方法,自顶向下来阅读
  2. 提纲挈领:摸清框架而避免在某个细节停留,如果对某个细节有疑问,记录下来回头深入去看
  3. 广度优先:每次在一个层面上通读一遍(比如第一次掌握主要的几个模块和它们之间的关系,第二次则是几个主要的类,第三次可能到了方法/函数层面),确保广度优先而不是深度优先
  4. 理清目的,分离职责:在不同层面弄清楚每个模块、类、方法的目的/职责,而不是如何实现这个目的/职责。因为任何算法都是为某个职责、目的服务,弄清楚目的而不在于如何实现目的,弄清楚Why而不是How to

高效阅读代码的能力背后:
  1. 大脑的运行方式——和CPU很像,当需要跟进进入到下一个层面(深度)的时候,需要把当前断点记下来,相关信息压入“堆栈”暂时放一放,等进入下一个层面回来恢复到之前的断点工作状态。想想大脑的堆栈和准确记忆能力显然不如CPU,所以尽量避免在不同层次来回穿越,甚至过于深入。必要时,借助一些电脑软件来帮助你阅读,例如UML工具的类图、时序图等
  2. 重点在目标/职责是什么,然后才是如何实现目标/职责:任何系统都是为了解决具体问题而存在。如何解决问题则体现在解决方案,代码只是实现解决方案。而解决方案在不同层面体现为功能模块的组合、具体函数/方法的组合、具体的算法实现(方法内部)等等。
    所以需要自顶向下的分解问题、解决问题的思路,自顶逐层往下,每个层面都搞清楚这个层面的全局脉络(广度优先)。
  3. 题外:做开发的弟兄们最容易出现的问题就是过于关注“how to”这样的实现问题,常见的场景例如:看到别人做了一个什么系统、软件、功能,第一反应是“这个简单,我也会”、“哟,这是怎么实现的?我好像不会”——无论你会不会,请克制你的技术实现冲动。首要问题是:Why——为何要这么实现?那一定是为某个目标、职责服务的。当你阅读别人已经写好的代码,那些代码肯定是为一个个大大小小的目标、职责服务的,所以先忽略How to,搞清楚它们每一个目标/职责,暂时忽略细节。待都弄清楚了,再来挑你感兴趣的地方深入去分析,有的是时间和机会。
    ——请克制技术冲动、实现冲动,这对你的职业生涯是非常有帮助的。已经度过了类似阶段的朋友不妨回顾一下这里面的心得体会。越是对自己的技术实现能力不自信的阶段,越容易出现类似问题。
    其实任何行业,往往随着经验和能力提升,越来越熟练的在抽象层面思考、擅长运用“自顶向下”的分解能力,并且有很强的全局观和逻辑性来保证在任何一个层面的展开都系统而全面(其实基于上一层作为依据展开也不容易遗漏)。举个自己的例子:曾经我的简历上列明我精通、掌握、熟悉各种技术和平台还有各种经验案例等等,后来改成一句话——擅长高效解决问题,并乐于解决复杂问题和新问题,尤其享受用创新方式解决问题。简历上写的求职方向就不再限制于软件相关了——当然1,这与其说是个人能力提升了,不如说找到了自己努力和享受的方向。这样的阶段,至少在思维上已经脱离了具体的软件设计开发相关技术背景的限制,有勇气面对任何行业任何问题;当然2,不要脱离实际的选择专业性要求过于强的行业和工作岗位进行比较;当然3,这些行业里的从业人员不也存在同样的阶段性问题么?
思考和讨论这类问题,对个人成长有提速作用。

个人以为有几种基础能力:
运算能力(大脑的堆栈容量)决定了能处理问题的大小和复杂程度(有生理上限)、思维模式(方法论)决定了处理大和复杂的问题效果和效率(扩充了生理上限)、自我克制(理解甚至控制生理本能)决定了排除干扰的能力,然后是经验积累(可重用模块:分为模式级别和具体实现级别的经验)。
——如同一个优秀的棋手。

母亲说我小时候喜欢玩线团和整理纽扣,可以坐在一个地方一动不动一个下午直到解开一个线团。
随着成长,我已经不满足于解开各种线团,甚至解开越来越大、越来越复杂的线团,而是尝试和追求另外一种方式:各角度观察、推理,理清头绪之后找准一个线头,拎起来轻轻一抖——哇,整个线团优雅的解开了——爽!

一个真正的领导者,在人群中默默观察,对外接的刺激不要立即有反应(自我克制),做那个清醒的了解目标和团队和自己的人(全局观),找到解决方法后选择最恰当的方式去影响和驱动周围的人。未必是聚光灯下的领导者,却是实际上的领导者,不需要权力就能驱动整个组织往有效解决问题的方向推进的领导者。
看过《安德的游戏》的朋友,推荐它的姐妹篇《安德的影子》,主角小豆子就是极好的例子(避免剧透到此打住)。

再往后。。。一下子没想好怎么表达,先打住吧,有朋友有兴趣我再分享进一步的心得。

最后,到这里也只好匿了,呵呵。 1. 要建立层次和结构
看代码不是看小说,线性地往下看就行了。看代码是为了理解代码,在脑子里建立起源代码背后的层次和结构的映射。为此,在开始分析项目之初,就要明确代码的子项目,包(名称空间),类的层次和结构,主要由哪些包构成,每个包大致做什么用。主要的类有哪些,各自的大致职责是什么。主要的类里面,又有哪些主要的方法。

2. 要抓住主干
任何的项目,有相当的代码是用来做一些琐碎的,事务性的事情的。要高效地理解和把握代码,我们就要把握主干。对于代码中的一些主要方法,或者流程,可以梳理出它们的主要步骤,次要的东西可以忽略不管,需要的时候再关注。

3. 要形成文档
如前面的几位答友所说,人脑子不善于记住方法间的进进出出之类的东西,在我们分析这些东西的同时,用一种有效的方式,把分析的结果记录下来,既保存了工作成果,更重要的是,帮助我们更容易进行分析,向深挖的时候,知道现在自己在哪里,向回退的时候,又退得出来,不至于迷路。类图,序列图,都是有用的文档形式,也可以用自己定义的更灵活的图表。好记性不如烂笔头,勤快动脑同时也勤快动手,看代码会容易很多。

4. 要合理运用各种可用手段
静态分析,当然是分析代码的基本手段;但是除了静态分析,如果你的代码也是可以运行的,运行它,观察它的调用堆栈,LOG,或者用调试工具进行跟踪。对于那些主要的方法,流程,有必要用动态跟踪的方式,弄清楚它的过程。这也会比静态分析更直接,更快地告诉你它到底走过哪些路径,执行了哪些方法。

个人习惯先看文档说明了解功能了再做个 demo,明白基础的功能后就从这个熟悉的点切入去看。


我还见过直接硬啃代码的牛人,对他而言,这种方式简单粗暴,速度快效果好。

热心网友 时间:2022-04-19 02:45

个人经验,

读文件有4种方法,
1 按行读
2 按规定大小字节读
3 按流读
4 随机读取文件

我认为第3种是最好的,而且他是通吃的,

下面是我从网上找来的,你看看有用吗?
====================================
前两天用到读写文件的操作,上网搜了一些这方面的资料。很有用的。

java中多种方式读文件
一、多种方式读文件内容。
1、按字节读取文件内容
2、按字符读取文件内容
3、按行读取文件内容
4、随机读取文件内容

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.Reader;
public class ReadFromFile {
/**
* 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
* @param fileName 文件的名
*/
public static void readFileByBytes(String fileName){
File file = new File(fileName);
InputStream in = null;
try {
System.out.println("以字节为单位读取文件内容,一次读一个字节:");
// 一次读一个字节
in = new FileInputStream(file);
int tempbyte;
while((tempbyte=in.read()) != -1){
System.out.write(tempbyte);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
try {
System.out.println("以字节为单位读取文件内容,一次读多个字节:");
//一次读多个字节
byte[] tempbytes = new byte[100];
int byteread = 0;
in = new FileInputStream(fileName);
ReadFromFile.showAvailableBytes(in);
//读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread = in.read(tempbytes)) != -1){
System.out.write(tempbytes, 0, byteread);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null){
try {
in.close();
} catch (IOException e1) {
}
}
}
}
/**
* 以字符为单位读取文件,常用于读文本,数字等类型的文件
* @param fileName 文件名
*/
public static void readFileByChars(String fileName){
File file = new File(fileName);
Reader reader = null;
try {
System.out.println("以字符为单位读取文件内容,一次读一个字节:");
// 一次读一个字符
reader = new InputStreamReader(new FileInputStream(file));
int tempchar;
while ((tempchar = reader.read()) != -1){
//对于windows下,rn这两个字符在一起时,表示一个换行。
//但如果这两个字符分开显示时,会换两次行。
//因此,屏蔽掉r,或者屏蔽n。否则,将会多出很多空行。
if (((char)tempchar) != 'r'){
System.out.print((char)tempchar);
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println("以字符为单位读取文件内容,一次读多个字节:");
//一次读多个字符
char[] tempchars = new char[30];
int charread = 0;
reader = new InputStreamReader(new FileInputStream(fileName));
//读入多个字符到字符数组中,charread为一次读取字符数
while ((charread = reader.read(tempchars))!=-1){
//同样屏蔽掉r不显示
if ((charread == tempchars.length)&&(tempchars[tempchars.length-1] != 'r')){
System.out.print(tempchars);
}else{
for (int i=0; i<charread; i++){
if(tempchars[i] == 'r'){
continue;
}else{
System.out.print(tempchars[i]);
}
}
}
}
} catch (Exception e1) {
e1.printStackTrace();
}finally {
if (reader != null){
try {
reader.close();
} catch (IOException e1) {
}
}
}
}
/**
* 以行为单位读取文件,常用于读面向行的格式化文件
* @param fileName 文件名
*/
public static void readFileByLines(String fileName){
File file = new File(fileName);
BufferedReader reader = null;
try {
System.out.println("以行为单位读取文件内容,一次读一整行:");
reader = new BufferedReader(new FileReader(file));
String tempString = null;
int line = 1;
//一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null){
//显示行号
System.out.println("line " + line + ": " + tempString);
line++;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null){
try {
reader.close();
} catch (IOException e1) {
}
}
}
}
/**
* 随机读取文件内容
* @param fileName 文件名
*/
public static void readFileByRandomAccess(String fileName){
RandomAccessFile randomFile = null;
try {
System.out.println("随机读取一段文件内容:");
// 打开一个随机访问文件流,按只读方式
randomFile = new RandomAccessFile(fileName, "r");
// 文件长度,字节数
long fileLength = randomFile.length();
// 读文件的起始位置
int beginIndex = (fileLength > 4) ? 4 : 0;
//将读文件的开始位置移到beginIndex位置。
randomFile.seek(beginIndex);
byte[] bytes = new byte[10];
int byteread = 0;
//一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。
//将一次读取的字节数赋给byteread
while ((byteread = randomFile.read(bytes)) != -1){
System.out.write(bytes, 0, byteread);
}
} catch (IOException e){
e.printStackTrace();
} finally {
if (randomFile != null){
try {
randomFile.close();
} catch (IOException e1) {
}
}
}
}
/**
* 显示输入流中还剩的字节数
* @param in
*/
private static void showAvailableBytes(InputStream in){
try {
System.out.println("当前字节输入流中的字节数为:" + in.available());
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
String fileName = "C:/temp/newTemp.txt";
ReadFromFile.readFileByBytes(fileName);
ReadFromFile.readFileByChars(fileName);
ReadFromFile.readFileByLines(fileName);
ReadFromFile.readFileByRandomAccess(fileName);
}
}

二、将内容追加到文件尾部

import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
* 将内容追加到文件尾部
*/
public class AppendToFile {
/**
* A方法追加文件:使用RandomAccessFile
* @param fileName 文件名
* @param content 追加的内容
*/
public static void appendMethodA(String fileName,String content){
try {
// 打开一个随机访问文件流,按读写方式
RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
// 文件长度,字节数
long fileLength = randomFile.length();
//将写文件指针移到文件尾。
randomFile.seek(fileLength);
randomFile.writeBytes(content);
randomFile.close();
} catch (IOException e){
e.printStackTrace();
}
}
/**
* B方法追加文件:使用FileWriter
* @param fileName
* @param content
*/
public static void appendMethodB(String fileName, String content){
try {
//打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(fileName, true);
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
String fileName = "C:/temp/newTemp.txt";
String content = "new append!";
//按方法A追加文件
AppendToFile.appendMethodA(fileName, content);
AppendToFile.appendMethodA(fileName, "append end. n");
//显示文件内容
ReadFromFile.readFileByLines(fileName);
//按方法B追加文件
AppendToFile.appendMethodB(fileName, content);
AppendToFile.appendMethodB(fileName, "append end. n");
//显示文件内容
ReadFromFile.readFileByLines(fileName);
}
}

-----------------------------------------------------------------------------------------------------------------------------------------------
写入文件

try{
FileWriter fw=new FileWriter(SystemConfig.getRealPath()+"WEB-INF/url.txt");
fw.write("movie"+name);
fw.close();
}catch(IOException e){
e.printStackTrace();
}

读文件中内容

try{
FileReader fr = null;
fr = new FileReader(SystemConfig.getRealPath()+"WEB-INF/url.txt");
BufferedReader br=new BufferedReader(fr);
String Line = null;
Line = br.readLine();
while(Line!=null){
s=Line;
Line=null;
br.close();
fr.close();
}
}catch(IOException e1){
e1.printStackTrace();
}

上传文件

try {
InputStream stream = getUpFile().getInputStream();//把文件读入
OutputStream bos = new FileOutputStream(filePath + "movie" +name);//建立一个上传文件的输出流
int bytesRead = 0;
byte[] buffer = new byte[1026];
while ( (bytesRead = stream.read(buffer, 0, 1026)) != -1) {
bos.write(buffer, 0, bytesRead);//将文件写入服务器
}
bos.close();
stream.close();
}catch(Exception e){
System.err.print(e);
}

热心网友 时间:2022-04-19 04:03

本来不想回答,翻到下面那些答复实在看不过去,就花点功夫整理下吧,希望对有人心能有帮助。

阅读分析源代码,一些有效的方法是:

1、阅读源代码的说明文档和API文档。

2、如果源代码有用法示例或向导,先阅读这个。

3、了解整个项目的模块结构,可以按模块进行阅读。

4、随时使用查找功能(或超链接)阅读关联类或关联方法。

5、对于有疑问的地方,不妨写几行单元测试。

6、由浅入深,由易到难,多阅读优秀的开源项目,代码阅读水平会突飞猛进。

热心网友 时间:2022-04-19 05:37

用DeBug,边跑边看后台

热心网友 时间:2022-04-19 07:29

阅读代码比较困难,阅读过的都加上注释,这样可能会高效吧

热心网友 时间:2022-04-19 09:37

占座
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
“晚来天欲雪,能饮一杯无?”是什么意思_出处及原文翻译_学习力 胸肌中部怎么练 血沉高是怎么回事,怎样才能降低啊! 中海锦江城多久交房 “QMS”作为“质量管理体系”的英文缩写,其背后理论及应用如何?_百度... 我用QQ登的快手绑定了一个电话号码,电话号码不用了,现在怎么能登得进去... 桂林银行白金客户条件 桂林银行最高等级卡 iQOO 11系列曝光,预计年底正式发布! vivo X90先别买?iQOO 11系列配置堪称豪华 梦见自己去苹果园摘四个苹果,有两个是连在一起的什么意思? 梦见苹果树上结满青苹果,可是每个苹果都爬有虫子,但我还是摘了 做梦梦见摘了好多苹果而且还吃了 mac 下有没有winscp和QUICKPWN这一类的软件 WinSCP2是个什么软件? 怎么下载我的世界SCP scp 166197怎么下 描写水果的日记(二年级水平,39字) 日记怎么写水果的 描写水果的日记三年级 怎么在电脑上画一横线百分之几在那里 三星note5怎么查看mac地址 lol和wow分别是什么意思 绝地求生sss 龙宗泉什么时候打的职业 在国外机场的简单用语 机场英语 机场安检员常用英语口语 机场地勤英文口语 我想急求有关机场地勤的英语口语对话资料,马上要去东航面试地勤,主要的工作时负责接机 谁能给我机场英语服务100句??谢谢 去哪里查找ISO质量体系认证文件 什么是ISO质量体系认证?我们单位现在需要,应该怎么办? pvc名片能双面印刷吗 我皮肤较黄穿橘色呢大衣配什么颜色围脖好看紫色可以吗? 橘色大衣配什么颜色围巾好看 时尚搭配首选 橘色大衣配什么颜色好看?橙色可以吗?提问 ALEVEL课程辅导班哪家好 橘色呢大衣搭配什么颜色围巾好看 晚上一觉醒来口干舌燥什么原因 背心上部痛是怎么回事 后背疼,上方中间,与肩胛骨平行的位置,主要是夜里,尤其是后半夜。也不是很疼,就是很不舒服的感觉,像 后背上部中间深度疼痛 成都欢乐谷门票怎么买最便宜 请问去成都欢乐谷用身份证在网上订票的话,可以不用本人的身份证吗? 成都欢乐谷如何买今天的门票 我要买两张欢乐谷门票,听说在网上买便宜一点 欢乐谷门票,网上订门票多少钱一个大人,一个小孩 上海欢乐谷的门票可不可以到网上去买,哪里比较便宜而且比较保险 想要在网上买成都欢乐谷的门票,哪个网站比较好? 深圳欢乐谷门票多少?网上订票是不是比较便宜?