问题 #2

java里的对象有几种创建方式?所有的对象都得new出来吗?

次阅读

答案

1 new

用new是最常见的方式,new可以创建一个对象

Student s1 = new Student()

注意:

Student s2 = s1;

这里没有new,所以并没有创建新的对象,s2, s1指向了同一对象

2 字面常量对象

String s = “afanihao”;

则s指向了一个常量对象,这里并没有new,但是右侧有一个对象

再比如

Integer a = 123;

这里没有new,但是右侧有一个对象。这处方式适合于基本数据类型,如String , Integer, Double等

3 反射

利用反射机制,可以根据 Class得到一个实例

Class cls = Student.class;

Object a = cls.getInstance( ); // 得到一个对象

Student s = (Student) a;

使用 getInstance() 可以创建一个对象


问题 #3

在 Java Web 网站开发时,为什么在写 Servlet , Filter 的时候不需要 main() 方法,却可以运行?

次阅读

答案

在 Java Web 开发时看不到 main() ,因为 Tomcat 程序本身就是一个 Java程序, main()方法在 Tomcat程序里。

实际上,Tomcat本身就是一个框架,它会加载APP, 读取 WEB-INF\web.xml 下的配置,从中读取相应的Filter 和 Servlet。

所以,当我们写好 Filter, Servlet后,只需要把 web.xml 里配置好。。然后,当Tomcat启动时,它会自动地加载我们写的 Fiter / Servlet。


问题 #4

怎么把一张图片直接存到数据库里?

通常,应该把文件放在文件系统(硬盘)上,在数据库里只存储图片文件的路径 。但是,如果想 图文文件直接存在数据库里,怎么实现呢?

次阅读

答案

由于图片数据较大,在MySQL中直接存储的话,应该选则 BLOB 类型的字段。

( 以下假设图片的大小为 100K 以下 , 太大的不适合 )

1 将字段类型设为 mediumtext

此字段可用于存储 <16MB 的文本

2 读取文件数据,转成Hex 或 base64

关于 Hex 和 base64 编码,参考 《项目应用篇》,数据的编码

将编码后的文本存到数据库中即可

// 写入过程,伪代码表示

byte[] buffer = new byte[fileSize] ;

fileStream.read ( buffer)

String base64str = base64Encode ( buffer ) 将数据转成base64字符串

String sql = “update YOUR_TABLE set thumb=’%s’ WHERE … “ 拼凑一个SQL

执行 sql …

// 读取过程,伪代码表示

String sql = ….

String base64str = … 从数据库中取读该列的值

byte[] imageData = base64Decode ( base64str ) 把 base64字符串转回byte[]

file.write ( imageData )

再次强调,图片还是要小一点,如果太大是真得不适合存到数据库的。


问题 #5

在 Java 里,怎么复制一个对象?

比如,

Rectangle a = new Rectangle ( 0, 0, 100, 40);

Rectangle b = a;

这里并没有复制对象,b和a指向的是同一个对象。那么,如果想根据a 复制一个新的对象,该怎么做呢?

次阅读

答案

注: 这里的 Rectangle 在来自 Java Swing 里的 Rectangle 类。

Rectangle  a = new Rectangle ( 0, 0, 100, 40);

Rectangle  b = new Rectangle();

b.x = a.x;

b.y = a.y;

b.width = a.width;

b.height = a.height;

以上代码,创建了两个 Rectangle 对象,它们的值完全相同。可以认为,基于a对象复制出一个新的对象b。

再来看一下,其实还有更简洁的写法:

Rectangle  a = new Rectangle ( 0, 0, 100, 40);

Rectangle  b = new Rectangle( a ); // 此处即复制出一个对象

为什么可以这么写? 因为在 java swing 里的 Rectangle类,还有一个构造方法:

public  class Rectangle

{

public Rectangle (Rectangle other )

{

this.x = other.x;

this.y = other.y;

this.width = other.width;

this.height = other.height;

}

...

}

所以,在 b = new Rectangle ( a ) 时,即执行的是这个构造方法。


问题 #6

在网络通讯时,IP地址表示一个主机。你和隔壁小王都在家里用QQ上网聊天,你发现你的IP是192.168.1.101,小明的IP也是192.168.1.101。请问:为什么两台IP地址相同的主机可以通讯?

次阅读

答案

实际上,全国有几百万台家庭电脑的IP都是192.168.1.XXX,但是,却不妨碍大家互相QQ聊天。

比如,

你的电脑A 192.168.1.101

你家路由器 192.168.1.1 (LAN口) / 202.188.14.139 (WAN口)

小明家路由器 192.168.1.1 (LAN口) / 134.12.98.5 (WAN口)

小明的主机B 192.168.1.101

你发出一条消息后,该消息依次经过:

( A ) >> 你家路由器 >> 。。。>> 小明家路由器 >> ( B )

简单地讲,你的消息将由路由器转发,真实发生的是两台路由器之间的通讯,而这两台路由的IP是不相同的。

大概的原因主是这样,具体的详细的原理讲解:请参考《网络通信篇》,关于交换机、路由器、端口映射的章节。


问题 #7

在Java里,equals() 与 == 有什么区别?

次阅读

答案

此问题在 《快速入门篇》11.6节里已经详细分析过。

==用于判断两个对象是否相同 (同一个对象)

比如,

Student a = new Student( … )

Student b = a;

则 a, b 其实指向同一个对象。

if ( a == b )

{

}

这个是成立的。

equals 用于判断两个对象是否相等(内容相等)

举个例子:你和小王都是18岁,则你和小王是equals()的。但是显然你们不是==的,因为你们是两个人。


问题 #8

在网盘上传大文件,一个G的文件有可能几秒中就上传完了。称为极速秒传,请问它是怎么做到的?

次阅读

答案

这个涉及到 MD5码,具体原理参考《项目应用篇》之”数据的校验”章节。

每个文件都要以生成一个MD5码,用公式表示为:

output = MD5 ( input File )

其中,输入input为文件数据,输出MD5码是一个16字节的数组 byte[16]

需要注意以下两条结论:

(1) 无论输入数据有多大,是10K还是10G,输出都是16字节

(2) 不同的文件,生成的MD5码是不同的。如果发现MD5相同,则认为原文件相同。

因此,当一个文件上传到网盘上后,网盘后台会增加一条记录:

( file, size, md5Code )

在上传文件之前,由客户端先对文件做MD5运算,得到MD5码。。然后交给后台查找是否有相同文件,后台如果发现有个文件的MD5码与之相同,则认为要上传的文件已经存在库里,不再重复上传。

举例来说,

小王上传一个 1G 的大视频,于是网盘后台记录下了这个文件的MD5值。

你拿到了这个视频文件,想上传到自己的网盘里,由于MD5值相同,后台判断此文件已经存在库中。于是你的上传过程省略(极速秒传), 后台直接引用了小王上传的那个文件。


问题 #9

Thread 与 Runnable 有什么区别和联系?

次阅读

答案

其实 Thread 和 Runable 没太大联系。

※ Runnable

Runnable 则是一个接口,一个通用的接口。

什么叫通用接口?

就是在你要自定义一个接口时,如果想不到合适的名字,则可以直接用Runnable。

比如,在 Swing高级篇 里,我们经常要自定义接口。比如,定义一个

public interface ClickListener

{

public void clicked();

}

其实呢,咱们不一定要自己定一个接口的,你定义的这个和Runnable有啥区别呢?

public interface Runnable

{

public void run();

}

就是名字变了,本质上没有区别。所以,我们可以直接使用Runnable,而不需要自己定义接口。

※ Thread

Thread是一个类,用于创建线程。

看一下JDK的文档,可以看到

Class Thread
All Implemented Interfaces:
Runnable

也就是说,Thread类实现了Runnable接口,所以不少人觉得Thread和Runnable有关系。其实没有太大的关系。

创建线程的时候,总是Thread,因为Thread代表一个线程。

( 当然,Timer也算是一个线程,另当别论 )


问题 #10

怎样理解优秀代码的三个标准:可读性,可重用性,可扩展性?

共 641 次阅读

答案

可读性,Readable

指一份代码干净清爽,容易读懂。简单地讲,能让别人1秒读懂的,就别让人花2秒!

多加点注释就好了吗? 错错错!代码如果写得好,一句注释都可以没有。因为代码即“文章”,它自身就可以表示意思和逻辑。

- 怎么样增加可读性?

 - 合理的架构设计 

 - 名字起得好

 - 多留点空白,不要挤在一起

 - 一行代码不要嵌套多层函数

 - 不是代码越简洁越好,而是越容易懂越好!代码短了,却有可能更难懂!

可重用性,Reusable

指一份代码可以直接拿到别的项目里、不加修改(或少量修改),即可重复使用。

不是有一个段子吗,高手都是 Ctrl + C 和 Ctrl + V ,为什么?

为什么人家的代码可以直接拷贝粘贴呢?因为人家代码封装的好、可以直接重用啊!

比如,在〖Java学习指南〗系列课程里,提供了上百个以 Af 打头的类,它们都是可以重用的。可以直接放在你的项目里使用。

可扩展性, Extensible

指的是一份设计,不但可以满足现在的需求,更可以适应将来的变化。

程序员老是抱怨:需求别再改啦,代码又得重构了!

为什么呢?因为你的设计眼光有点短,不能适应可能的变化,不可扩展。

举个例子,在网络课堂上,有的课程是章节式的,有的课程是一字排开、不非章的。

那么,章节式编排就是可扩展的。无章编排则是不可扩展的。

比如,将来要在课程里插入新的一节:

- 对于连续编排的课程,如果要在里面插入一节,则要修改后面几十节的标题

- 对于章节编排的课程,影响最多一章,对后面的章节没有影响。这便是可扩展的设计。


一个好奇的人