考官:什么学历?
考生:小学没毕业。
考官:打过架吗?
考生:家常便饭。
考官:有案底吗?
考生:刚刚出来。
考官:体能呢?
考生:还可以,一脚可以踢翻小贩的小三轮车。
考官:敢拿人家的东西吗?
考生:这是我的强项,就像拿自己的东西一样。
考官:老头敢打么?
考生:小菜,俺爹就是让俺打残的。
考官:你考试通过了,我们城管需要的就是你这样的人才!
考官:再问一句 出事了怎么办?
考生:就说是临时工.
考官:今晚上班
在Eclipse里 export 选 JavaDoc,在向导的最后一页的Extra JavaDoc Options 里填上参数即可
比如项目采用的是UTF-8的编码就填:-encoding UTF-8 -charset UTF-8
@Override是什么?jdk1.5及以上版本用过eclipse自动生成接口实现类的程序员,应该会觉得眼熟的,它是Annotation,中文意思是注解。
@Override是干什么的?顾名思义,覆盖,就是覆盖父类的实现。
为什么问它是否是鸡肋?我上面说过,在jdk1.5及以上版本用eclipse生成接口实现类,其中的方法会给你自动标注上@Override,我们一般认为那是实现而不是覆盖,因为接口本身是没有实现方法的,但是却被标注成@Override,在中文开发者(主要是指傻小子本人)而言会觉得那是鸡肋,看到就删除,删除还删除。
某天,傻小子再重构代码,改了下接口方法的名字,发现实现类报错了。究其原因,接口方法名改了,相当于新增了一个方法,那么就需要我们实现了就应该好。理想是美好的,现实是残酷的。编译还是通不过,发现了罪魁祸首@Override。删除掉它,就好了,编译通过了。真的好了吗,明显是自欺欺人。代码是编译通过了,但是这不是多出一个不会被调用的无主孤魂了吗?没有在接口被声明,不会被外部调用的方法,这不是浪费吗?
经此往后,傻小子不得不感慨,存在即合理的。
@Override既然存在了,那么一定是有它的用处的,这里就告诉我们了,它能够自我检测被标注的实现是否存在于接口中。
名字解析:
@Override注释能实现编译时检查,你可以为你的方法添加该注释,以声明该方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报 错。
1)登录管理自己的GAE https://appengine.google.com
2)找到并点击 “Application Settings”
3)看到“Domain Setup”下面有一行字和一个“Add Domain”按钮,
这行字的内容是:
Want to host your application on another domain? Google App Engine uses Google Apps to manage domains. Learn more
先别点击按钮,先点“Google Apps”,弹出一个窗口,在窗口找到“标准”或“Standard Edition”字样,点击它,
如果找不到可直接点击这个链接http://www.google.com/apps/intl/en/group/index.html
4)点“开始使用”或“get started”按钮,接下来就按提示操作即可,注意以下两点:
A:管理员:我拥有或控制此域名,如 yourdomain.com
B:所在地区选中国香港
5)申请后google要验证你所申请时用的域名,看看是不是你自己的,在管理界面上找到“验证域名所有权”,并点击它,google提供两种验证方式,设置域名的CNAME或上传一个html文件到域名空间里,建议选择设置CNAME,这时google会给你一个字符窜如“googlefffffwasdf8a1cb73c”之类,让你增加该CNAME,并指向google.com,添加后先点击(如:googlefffffwasdf8a1cb73c.yourdomain.com),如果看到能转到google.com 主页,说明解析生效了,那就点“验证”,google会提示在48小时内会自动验证,你可以再次点击“验证域名所有权”,重复上面的步骤,我都是通过这样多点几次,直到不再显示要你验证的提示。如果顺利这一步就完成了。
6)回到GAE控制面板,现在可以点击步骤3里的“Add Domain”按钮,输入你的域名yourdomain.com,这时会转到刚才你申请的“Google Apps”页面,添加新域名输入 “www(或其它)”.yourdomain.com。接下来要到你域名的控制面板,添加CNAME,即你刚才所填的“www(或其它)”,让它指向ghs.google.com,注意:指向官方的ghs.google.com 时只有在国外能打开,要想国内能正常访问还得找山寨的ghs,如http://www.you8g.com/ 刚才去看了:当前剩余域名名额 0/3000 没有名额了。(补充:这个网站还会新加的,一用完就会增加名额,所以说总是有名额的。7.14显示“877/4000”,很期待他们的服务越来越稳定。)
如果第6步顺利完成了绑定域名就完成了,验证方法,用代理打开你绑定的域名,如果能打开就绑定正常了。
1. I see. 我明白了。
2. I quit! 我不干了!
3. Let go! 放手!
4. Me too. 我也是。
5. My god! 天哪!
6. No way! 不行!
7. Come on. 来吧(赶快)
8. Hold on. 等一等。
9. I agree。 我同意。
10. Not bad. 还不错。
11. Not yet. 还没。
12. See you. 再见。
13. Shut up! 闭嘴!
14. So long. 再见。
15. Why not? 好呀! (为什么不呢?)
16. Allow me. 让我来。
17. Be quiet! 安静点!
18. Cheer up! 振作起来!
19. Good job! 做得好!
20. Have fun! 玩得开心!
21. How much? 多少钱?
22. I’m full. 我饱了。
23. I’m home. 我回来了。
24. I’m lost. 我迷路了。
25. My treat. 我请客。
26. So do I. 我也一样。
27. This way。 这边请。
28. After you. 您先。
29. Bless you! 祝福你!
30. Follow me. 跟我来。
31. Forget it! 休想! (算了!)
32. Good luck! 祝好运!
33. I decline! 我拒绝!
34. I promise. 我保证。
35. Of course! 当然了!
36. Slow down! 慢点!
37. Take care! 保重!
38. They hurt. (伤口)疼。
39. Try again. 再试试。
40. Watch out! 当心。
41. What’s up? 有什么事吗?
42. Be careful! 注意!
43. Bottoms up! 干杯(见底)!
44. Don’t move! 不许动!
45. Guess what? 猜猜看?
46. I doubt it 我怀疑。
47. I think so. 我也这么想。
48. I’m single. 我是单身贵族。
49. Keep it up! 坚持下去!
50. Let me see.让我想想。
51. Never mind.不要紧。
52. No problem! 没问题!
53. That’s all! 就这样!
54. Time is up. 时间快到了。
55. What’s new? 有什么新鲜事吗?
56. Count me on 算上我。
57. Don’t worry. 别担心。
58. Feel better? 好点了吗?
59. I love you! 我爱你!
60. I’m his fan。 我是他的影迷。
61. Is it yours? 这是你的吗?
62. That’s neat. 这很好。
63. Are you sure? 你肯定吗?
64. Do l have to 非做不可吗?
65. He is my age. 他和我同岁。
66. Here you are. 给你。
67. No one knows . 没有人知道。
68. Take it easy. 别紧张。
69. What a pity! 太遗憾了!
70. Any thing else? 还要别的吗?
71. To be careful! 一定要小心!
72. Do me a favor? 帮个忙,好吗?
73. Help yourself. 别客气。
74. I’m on a diet. 我在节食。
75. Keep in Touch. 保持联络。
76. Time is money. 时间就是金钱。
77. Who’s calling? 是哪一位?
78. You did right. 你做得对。
79. You set me up! 你出卖我!
80. Can I help you? 我能帮你吗?
81. Enjoy yourself! 祝你玩得开心!
82. Excuse me,Sir. 先生,对不起。
83. Give me a hand! 帮帮我!
84. How’s it going? 怎么样?
85. I have no idea. 我没有头绪。
86. I just made it! 我做到了!
87. I’ll see to it 我会留意的。
88. I’m in a hurry! 我在赶时间!
89. It’s her field. 这是她的本行。
90. It’s up to you. 由你决定。
91. Just wonderful! 简直太棒了!
92. What about you? 你呢?
93. You owe me one.你欠我一个人情。
94. You’re welcome. 不客气。
95. Any day will do. 哪一天都行夕
96. Are you kidding? 你在开玩笑吧!
97. Congratulations! 祝贺你!
98. T can’t help it. 我情不自禁。
99. I don’t mean it. 我不是故意的。
100. I’ll fix you Up. 我会帮你打点的
101. It sounds great!. 听起来很不错。
102. It’s a fine day。 今天是个好天。
103. So far,So good. 目前还不错。
104. What time is it? 几点了?
105. You can make it! 你能做到!
106. Control yourself! 克制一下!
107. He came by train. 他乘火车来。
108. He is ill in bed. 他卧病在床。
109. He lacks courage. 他缺乏勇气。
110. How’s everything? 一切还好吧?
111. I have no choice. 我别无选择。
112. I like ice-cream. 我喜欢吃冰淇淋。
113. I love this game. 我钟爱这项运动。
114. I’ll try my best. 我尽力而为。
115. I’m On your side. 我全力支持你。
116. Long time no see! 好久不见!
117. No pain,no gain. 不劳无获。
118. Well,it depends 噢,这得看情况。
119. We’re all for it. 我们全都同意。
120. What a good deal! 真便宜!
121. What should I do? 我该怎么办?
122. You asked for it! 你自讨苦吃!
123. You have my word. 我保证。
124. Believe it or not! 信不信由你!
125. Don’t count on me.别指望我。
126. Don’t fall for it! 别上当!
127. Don’t let me down. 别让我失望。
128. Easy come easy go. 来得容易,去得快。
129. I beg your pardon. 请你原谅。
130. I beg your pardon? 请您再说一遍(我没有听清)。
131. I’ll be back soon. 我马上回来。
132. I’ll check it out. 我去查查看。
133. It’s a long story. 说来话长。
134. It’s Sunday today. 今天是星期天。
135. Just wait and see! 等着瞧!
136. Make up your mind. 做个决定吧。
137. That’s all I need. 我就要这些。
138. The view is great. 景色多么漂亮!
139. The wall has ears. 隔墙有耳。
140. There comes a bus. 汽车来了。
141. What day is today? 今天星期几?
142. What do you think? 你怎么认为?
143. Who told you that? 谁告诉你的?
144. Who’s kicking off? 现在是谁在开球?
145. Yes,I suppose So. 是的,我也这么认为。
146. You can’t miss it 你一定能找到的。
147. Any messages for me? 有我的留言吗?
148. Don’t be so modest. 别谦虚了。
149. Don’t give me that! 少来这套!
150. He is a smart boy. 他是个小机灵鬼。
151. He is just a child. 他只是个孩子。
152. I can’t follow you. 我不懂你说的。
153. I felt sort of ill. 我感觉有点不适。
154. I have a good idea! 我有一个好主意。
155. It is growing cool. 天气渐渐凉爽起来。
156. It seems all right. 看来这没问题。
157. It’s going too far. 太离谱了。
158. May I use your pen? 我可以用你的笔吗?
159. She had a bad cold. 她患了重感冒。
160. That’s a good idea. 这个主意真不错。
161. The answer is zero. 白忙了。
162. What does she like? 她喜欢什么?
163. As soon as possible! 越快越好!
164. He can hardly speak. 他几乎说不出话来。
165. He always talks big. 他总是吹牛。
166. He won an election. 他在选举中获胜。
167. I am a football fan. 我是个足球迷。
168. If only I could fly. 要是我能飞就好了。
169. I’ll be right there. 我马上就到。
170. I’ll see you at six. 我六点钟见你。
171. IS it true or false? 这是对的还是错的?
172. Just read it for me. 就读给我听好了。
173. Knowledge is power. 知识就是力量。
174. Move out of my way! 让开!
175. Time is running out. 没时间了。
176. We are good friends. 我们是好朋友。
177. What’s your trouble? 你哪儿不舒服?
178. You did fairly well! 你干得相当不错1
179. Clothes make the man. 人要衣装。
180. Did you miss the bus? 你错过公共汽车了?
181. Don’t lose your head。 不要惊慌失措。
182. He can’t take a joke. 他开不得玩笑。
183. He owes my uncle $100.他欠我叔叔100美元。
184. How are things going? 事情进展得怎样?
185. How are you recently? 最近怎么样?
186. I know all about it. 我知道有关它的一切。
187. It really takes time. 这样太耽误时间了。
188. It’s against the law. 这是违法的。
189. Love me,love my dog. (谚语)爱屋及乌。
190. My mouth is watering. 我要流口水了。
191. Speak louder,please. 说话请大声点儿。
192. This boy has no job. 这个男孩没有工作。
193. This house is my own. 这所房子是我自己的。
194. What happened to you? 你怎么了?
195. You are just in time. 你来得正是时候。
196. You need to workout. 你需要去运动锻炼一下。
197. Your hand feels cold. 你的手摸起来很冷。。
198. Don’t be so childish. 别这么孩子气。
199. Don’t trust to chance! 不要碰运气。
200. Fasten your seat belt. 系好你的安全带。
201. He has a large income. 他有很高的收入。
202. He looks very healthy. 他看来很健康。
203. He paused for a reply. 他停下来等着·回答。
204. He repaired his house. 他修理了他的房子。
205. He suggested a picnic. 他建议搞一次野餐。
206. Here’s a gift for you. 这里有个礼物送给你。
207. How much does it cost? 多少钱?
208. I caught the last bus. 我赶上了最后一班车。
209. I could hardly speak. 我简直说不出话来。
210. I’ll have to try that. 我得试试这么做。
211. I’m very proud of you. 我为你感到非常骄傲。
212. It doesn’t make sense. 这没有意义(不合常理)。
213. Make yourself at home. 请不要拘礼。
214. My car needs washing. 我的车需要洗一洗。
215. None of your business! 与你无关!
216. Not a sound was heard. 一点声音也没有。
217. That’s always the case. 习以为常了。
218. The road divides here. 这条路在这里分岔。
219. Those are watermelons. 那些是西瓜。
220. What a nice day it is! 今天天气真好!
221. What’s wrong with you? 你哪里不对劲?
222. You are a chicken. 你是个胆小鬼。
223. A lovely day,isn’t it? 好天气,是吗?
224. He is collecting money. 他在筹集资金。
225. He was born in New York. 他出生在纽约。
226. He was not a bit tired. 他一点也不累。
227. I will be more careful. 我会小心一些的,
228. I will never forget it. 我会记着的。
229. It is Just what I need. 这正是我所需要的。
230. It rather surprised me. 那事使我颇感惊讶。
231. Just around the comer. 就在附近。
232. Just for entertainment. 只是为了消遣一下。
233. Let bygones be bygones. 过去的,就让它过去吧。
234. Mother doesn’t make up. 妈妈不化妆。
235. Oh,you are kidding me. 哦,你别拿我开玩笑了。
236. She has been to school. 她上学去了。
237. Skating is interesting. 滑冰很有趣。
238. Supper is ready at six. 晚餐六点钟就好了。
239. That’s a terrific idea! 真是好主意!
240. What horrible weather! 这鬼天气!
241. Which would you prefer? 你要选哪个?
242. Does she like ice-cream? 她喜欢吃冰淇淋吗?
243. First come first served. 先到先得。
244. Great minds think alike. 英雄所见略同。
245. He has a sense of humor. 他有幽默感。
246. He is acting an old man. 他正扮演一个老人。
247. He is looking for a job. 他正在找工作。
248. He doesn’t care about me. 他并不在乎我。
249. I develop films myself. 我自己冲洗照片。
250. I felt no regret for it. 对这件事我不觉得后悔。
251. I get up at six o’clock. 我六点起床。
252. I meet the boss himself. 我见到了老板本人。
253. I owe you for my dinner. 我欠你晚餐的钱。
254. I really enjoyed myself. 我玩得很开心。
255. I’m fed up with my work! 我对工作烦死了!
256. It’s no use complaining. 发牢骚没什么用。
257. She’s under the weather. 她心情·不好。
258. The child sobbed sadly. 小孩伤心地抽泣着。
259. The rumor had no basis. 那谣言没有·根据。
260. They praised him highly. 他们大大地表扬了他。
261. Winter is a cold season. 冬天是一个,寒冷的季节。
262. You can call me any time. 你可以随时打电话给我。
263. 15 divided by3 equals 5. 15除以3等于5。
264. All for one,one for all. 我为人人,人人为我。
265. East,west,home is best. 金窝,银窝,不如自己的草窝。
266. He grasped both my hands. 他紧握住我的双手。
267. He is physically mature. 他身体己发育成熟。
268. I am so sorry about this. 对此我非常抱歉(遗憾)。
269. I can’t afford a new car. 我买不起一部新车。
270. I do want to see him now. 我现在确实很想去见他。
271. I have the right to know. 我有权知道。
272. I heard some one laughing. 我听见有人在笑。
273. I suppose you dance much. 我想你常常跳舞吧。
274. I walked across the park. 我穿过了公园。
275. I’ll just play it by ear. 我到时随机应变。
276. I’m not sure I can do it. 恐怕这事我干不了。
277. I’m not used to drinking. 我不习惯喝酒。
278. Is the cut still painful? 伤口还在痛吗?
279. It’s too good to be true! 好得难以置信。
280. Jean is a blue-eyed girl. 珍是个蓝眼睛的女孩。
281. Let’s not waste our time. 咱们别浪费时间了。
282. May I ask some questions? 我可以问几个问题吗?
283. Money is not everything. 金钱不是一切。
284. Neither of the men spoke. 两个人都没说过话。
285. Stop making such a noise. 别吵了。
286. That makes no difference. 没什么区别。
287. The price is reasonable. 价格还算合理。
288. They crowned him king. 他们拥立他为国王。
289. They’re in red and white. 他们穿着红白相间的衣服。
290. We all desire happiness. 我们都想要幸福。
291. We just caught the plane 我们刚好赶上了飞机。
292. What shall we do tonight? 我们今天晚上去干点儿什么呢?
293. What’s your goal in life 你的人生目标是什么?
294. When was the house built? 这幢房子是什么时候建造的?
295. Why did you stay at home? 为什么呆在家里?
296. Would you like some help? 需要帮忙吗?
297. You mustn’t aim too high 你不可好高骛远。
298. You’re really killing me! 真是笑死我了!
299. You’ve got a point there. 你说得挺有道理的。
300. Being criticized is awful! 被人批评真是痛苦
301. Did you enter the contest? 你参加比赛了吗?
302. Do you accept credit cards? 你们收信用卡吗?
303. Don’t cry over spilt milk. 不要做无益的后悔。
304. Don’t let chances pass by. 不要让机遇从我们身边溜走。
305. He owned himself defeated. 他承认自己失败了。
306. He seems at little nervous. 他显得有点紧张。
307. He strolls about the town. 他在镇上四处遛达。
308. Her tooth ached all night. 她牙疼了一整夜。
309. How about a drink tonight? 今晚喝一杯怎样?
310. I can do nothing but that. 我只会做那件事。
311. I get hold of you at last. 我终于找到你了。
312. I have a surprise for you.我有一个意想不到的东西给你看。
313. I like all kinds of fruit. 我喜欢各种各样的水果。
314. I saw it with my own eyes. 我亲眼所见。
315. I will arrange everything. 我会安排一切的。
316. I wish I knew my neighbor. 我很想认识我的邻居。
317. I would like to check out. 我想结帐。
318. It has be come much cooler. 天气变得凉爽多了。
319. It’s time you went to bed. 你早就该睡觉了。
320. No spitting on the street. 禁止在大街上吐痰。
321. She was totally exhausted. 她累垮了。
322. Show your tickets,please. 请出示你的票。
323. Thank you for your advice. 谢谢你的建议。
324. That’s the latest fashion. 这是最流行的款式。
325. The train arrived on time. 火车准时到达。
326. There go the house lights. 剧院的灯光灭了。
327. They are paid by the hour. 他们按时取酬。
328. Things are getting better. 情况正在好转。
329. Wake me up at five thirty. 请在五点半叫醒我。
330. We are all busy with work. 我们都忙于工作。
331. Where do you want to meet? 你想在哪儿见面?
332. You can get what you want. 你能得到你想要的。
333. A barking dog doesn’t bite! 吠犬不咬人。
334. Are you free this Saturday? 你这个星期六有空吗?
335. Be careful not to fall ill. 注意不要生病了。
336. Being a mother is not easy. 做一个母亲是不容易的。
337. Brevity is the soul of wit. 简洁是智慧的精华。
338. Cancer is a deadly disease. 癌症是一种致命的疾病。
339. Did you fight with others? 你又和别人打架了吗?
340. Don’t dream away your time. 不要虚度光阴。
341. Don’t keep me waiting long. 不要让我等得太久。
342. He has a remarkable memory. 他有惊人的记忆力。
343. He has completed the task. 他完成了这个任务。
344. He has quite a few friends. 他有不少的朋友。
345. He is capable of any crime.他什么样的坏事都能干得出来。
346. He walks with a quick pace. 他快步走路。
347. He was not a little tired. 他很累。
348. His looks are always funny. 他的样子总是滑稽可笑。
349. How about going to a movie? 去看场电影怎么样?
350. I think I’ve caught a cold.我想我得了感冒。
351. I was taking care of Sally. 我在照顾萨莉。
352. I wish I lived in NEWYORK. 我希望住在纽约。
353. I’m very glad to hear that. 很高兴听你这样说。
354. I’m your lucky fellow then. 我就是你的幸运舞伴啦!
355. It’s none of your business! 这不关你的事儿!
356. No littering on the campus. 在校园内不准乱丢废物。
357. She is a good-looking girl. 她是一个漂亮女孩。
358. She mended the broken doll. 她修补了破了的洋娃娃。
359. So I just take what I want. 那么我只拿我所需要的东西。
360. Spring is a pretty season, 春天是一个好季节。
361. The figure seems all Right. 数目看起来是对的。
362. The stars are too far away. 星星太遥远了。
363. The whole world knows that. 全世界都知道。
364. Tomorrow will be a holiday. 明天放假。
365. We walk on the garden path. 我们走在花园小径上。
366. What you need is just rest. 你需要的就是休息。
367. What’s your favorite steps? 你最喜欢跳什么舞?
368. You’d better let her alone.你们最好是让她一个人呆会儿。
369. A lost chance never returns. 错过的机会永不再来。
370. Don’t let this get you down. 不要为此灰心丧气。
371. He shot the lion with a gun. 他用枪把狮子打死了。
372. I don’t think you are right. 我认为你是不对的。
373. I have never seen the movie. 我从未看过那部电影。
374. I haven’t seen you for ages. 我好久没见到你了。
375. I was alone,but not lonely.我独自一人,但并不觉得寂寞。
376. I went there three days ago. 我三天前去过那儿。
377. It’s a friendly competition. 这是一场友谊赛。
378. It’s very thoughtful of you. 你想得真周到。
379. May I speak to Lora,please? 我能和劳拉说话吗?
380. Mr.Wang is fixing his bike. 王先生在修他的自行车。
381. My brother is see king a job. 我弟弟正在找工作。
382. Nancy will retire next year. 南希明年就退休了。
383. Neither you nor he is wrong. 你没错,他也没错。
384. Opportunity knocks but once. 机不可失,时不再来。
385. She dressed herself hastily. 她匆忙穿上衣服。
386. She hired a car by the hour.她租了一辆按钟点计费的汽车。
387. Someone is ringing the bell. 有人在按门铃。
388. The Smiths are my neighbors. 史密斯一家是我的邻居。
389. These shoes don’t fit right. 这双鞋不太合适。
390. This is only the first half. 这才是上半场呢。
391. This pen doesn’t write well. 这钢笔不好写。
392. Would you like a cup of tea? 你想喝杯茶吗?
393. You really look sharp today. 你今天真漂亮。
394. Another cat came to my house. 又有一只猫来到我家了。
395. Check your answers with mine.把你的答案跟我的核对一下。
396. Don’t keep the truth from me. 别瞒着我事实真相。
397. Everything has its beginning. 凡事都有开端。
398. He came to the point at once. 他一下子就说到了点子上。
399. He fell behind with his work. 他工作落后了。
400. He is the happiest man alive. 他是世界上最快乐的人。
401. He neither smokes nor drinks. 他既不抽烟也不喝酒。
402. He ran his horse up the hill. 他策马跑上小山。
403. He reminds me of his brother. 他使我想起了他的弟弟。
404. He was efficient in his work. 他工作效率高。
405. He will do anything but work.只要不是干活,他干什么都行。
406. His father runs a restaurant. 他的父亲经营一家餐馆。
407. I have something to tell you. 我有事要告诉你。
408. I smelled a smell of cooking. 我闻到了烧菜做饭的味道。
409. I want to see the film again. 我真想再看一遍。
410. I’ve got too much work to do. 我要做的工作太多了。
411. Let’s go for a walk,shall we? 咱们出去走走,好吗?
412. Please let me check the bill. 请让我核对一下帐单。
413. Plenty of sleep is healthful. 充足的睡眠有益于健康。
414. The sun comes up in the east. 太阳从东方升起。
415. This is because we feel pain. 这是因为我们能感到疼痛。
416. What do you desire me to do? 你想要我做什么?
417. What you said was quite true. 你所说的完全符合事实。
418. You can either stay or leave. 你或者留下或者离开。
419. Your life is your own affair. 你的生活是你自己的事。
420. All that glitters is not gold. 发闪光的不全是黄金。
421. Are you going to have a party? 你要举行聚会吗?
422. Aren’t you concerned about it? 难道你不担心吗?
423. Don’t forget to keep in touch. 别忘了保持联系。
424. He broke his words once again. 他又一次违背了诺言。
425. He is in his everyday clothes. 他穿着平常的衣服。
426. He is taller than I by ahead. 他比我高一头。
427. He led them down the mountain. 他带他们下山。
428. He was trained to be a lawyer. 他被培养成一名律师。
429. I am afraid that l have to go. 我要走了。
430. I don’t have any cash with me. 我身上没带现金。
431. I have been putting on weight. 我开始发胖了。
432. I have just finished the book. 我刚刚读完这本书。
433. I was late for work yesterday, 我昨天上班迟到了。
434. It appears to be a true story. 这故事似乎是真的。
435. I’ve got to start working out. 我必须开始做健身运动了。
436. Japan is to the east of China. 日本在中国的东部。
437. John asked Grace to marry him, 约翰向格雷斯求婚。
438. My watch is faster than yours. 我的表比你的表快。
439. New China was founded in l949. 1949年新中国成立。
440. Thanks for your flattering me. 多谢你的夸奖。
441. They charged the fault on him. 他们把过失归咎于他。
442. This car is in good condition. 这车性能很好。
443. This work itself is very easy. 这件工作本身很容易。
444. Truth is the daughter of time. 时间见真理。
你要想找一帅哥就别来了,你要想找一钱包就别见了。硕士学历以上的免谈,女企业家免谈(小商小贩除外),省得咱们互相都会失望。刘德华和阿汤哥那种才貌双全的郎君是不会来征你的婚的。当然我也没做诺丁山的梦,您要真是一仙女我也接不住,没期待您长得跟画报封面一样看一眼就魂飞魄散。外表时尚,内心保守,身心都健康的一般人就行。要是多少还有点婉约那就更靠谱了。心眼别太多,岁数别太小,会叠衣服。每次洗完烫平叠得都像刚从商店里买回来的一样。说得够具体了吧!自我介绍一下,我岁数已经不小了,日子小康,抽烟不喝酒。留学生身份出去的,在国外生活了十几年,没正经上过学,蹉跎中练就一身生存技能,现在学无所成海外归来。实话实说,应该定性为一只没有公司、没有股票、没有学位的“三无伪海龟(海归)”。人品五五开,不算老实,但天生胆小。杀人不犯法我也下不去手,总体而言还是属于对人群对社会有益无害的一类。
有意者电联,非诚勿扰。
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复 制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用, 可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑 的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在 当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定 位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或 View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速 显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速 显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小 键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用 Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正 向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一 个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关 闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为 小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要 在匹配符里面,后面到前面,则反之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是 Alt+Shift开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多 劳动力)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修 改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取 成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合 并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药 (Undo)
编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一 个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全 局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅 助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java 编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元 素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文 本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y
查 看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-
窗口
作用 域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑 器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全 局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示 标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-
导 航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全 局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资 源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一 个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类 型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java 编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至 行 Ctrl+L
搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全 局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G
文 本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下 滚行 Ctrl+↓
文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全 局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关 闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N
项目
作 用域 功能 快捷键
全局 全部构建 Ctrl+B
源代码
作用域 功能 快捷键
Java编辑 器 格式化 Ctrl+Shift+F
Java编辑器 取消注释 Ctrl+\
Java编辑器 注释 Ctrl+/
Java 编辑器 添加导入 Ctrl+Shift+M
Java编辑器 组织导入 Ctrl+Shift+O
Java编辑器 使用 try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。
运 行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入 选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全 局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行 至行 Ctrl+R
全局 执行 Ctrl+U
重构
作用域 功能 快捷键
全局 撤销重 构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内 联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重 做 Alt+Shift+Y
1、mvn archetype:create -DgroupId=org.david.app -DartifactId=mywebapp -DarchetypeArtifactId=maven-archetype-webapp
2、cd mywebapp
mvn eclipse:eclipse
导入eclipse工程
(或者直接从eclipse中导入maven工程)
3、添加servlet依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
4、添加源代码目录src/main/java
将源代码放在该目录下。
5、添加jetty插件
<build>
<finalName>mywebapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
6、用jetty调试
命令行:mvn jetty:run
译者注 :你可能会觉得Java很简单,Object的equals实现也会非常简单,但是事实并不是你想象的这样,耐心的读完本文,你会发现你对Java了解的是如此的少。如果这篇文章是一份Java程序员的入职笔试,那么不知道有多少人会掉落到这样的陷阱中。原文转自http://www.artima.com/lejava/articles/equality.html 三位作者都是不同领域的大拿,有兴趣的读者可以从上面这个连接直接去阅读原文。
摘要
本文描述重载equals方法的技术,这种技术即使是具现类的子类增加了字段也能保证equal语义的正确性。
在《Effective Java》的第8项中,Josh Bloch描述了当继承类作为面向对象语言中的等价关系的基础问题,要保证派生类的equal正确性语义所会面对的困难。Bloch这样写到:
除非你忘记了面向对象抽象的好处,否则在当你继承一个新类或在类中增加了一个值组件时你无法同时保证equal的语义依然正确
在《Programming in Scala》中的第28章演示了一种方法,这种方法允许即使继承了新类,增加了新的值组件,equal的语义仍然能得到保证。虽然在这本书中这项技术是在使用Scala类环境中,但是这项技术同样可以应用于Java定义的类中。在本文中的描述来自于Programming in Scala中的文字描述,但是代码被我从scala翻译成了Java
常见的等价方法陷阱
java.lang.Object 类定义了equals这个方法,它的子类可以通过重载来覆盖它。不幸的是,在面向对象中写出正确的equals方法是非常困难的。事实上,在研究了大量的Java代码后,2007 paper的作者得出了如下的一个结论:
几乎所有的equals方法的实现都是错误的!
这个问题是因为等价是和很多其他的事物相关联。例如其中之一,一个的类型C的错误等价方法可能意味着你无法将这个类型C的对象可信赖的放入到容器中。比如说,你有两个元素elem1和elem2他们都是类型C的对象,并且他们是相等,即elem1.equals(elm2)返回ture。但是,只要这个equals方法是错误的实现,那么你就有可能会看见如下的一些行为:
Set hashSet<C> = new java.util.HashSet<C>();
hashSet.add(elem1);
hashSet.contains(elem2); // returns false!
当equals重载时,这里有4个会引发equals行为不一致的常见陷阱:
1. 定义了错误的equals方法签名(signature) Defining equals with the wrong signature.
2. 重载了equals的但没有同时重载hashCode的方法。 Changing equals without also changing hashCode.
3. 建立在会变化字域上的equals定义。 Defining equals in terms of mutable fields.
4. 不满足等价关系的equals错误定义 Failing to define equals as an equivalence relation.
在剩下的章节中我们将依次讨论这4中陷阱。
陷阱1:定义错误equals方法签名(signature)
考虑为下面这个简单类Point增加一个等价性方法:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// …
}
看上去非常明显,但是按照这种方式来定义equals就是错误的。
// An utterly wrong definition of equals
public boolean equals(Point other) {
return (this.getX() == other.getX() && this.getY() == other.getY());
}
这个方法有什么问题呢?初看起来,它工作的非常完美:
Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
Point q = new Point(2, 3);
System.out.println(p1.equals(p2)); // prints true
System.out.println(p1.equals(q)); // prints false
然而,当我们一旦把这个Point类的实例放入到一个容器中问题就出现了:
import java.util.HashSet;
HashSet<Point> coll = new HashSet<Point>();
coll.add(p1);
System.out.println(coll.contains(p2)); // prints false
为什么coll中没有包含p2呢?甚至是p1也被加到集合里面,p1和p2是是等价的对象吗?在下面的程序中,我们可以找到其中的一些原因,定义p2a是一个指向p2的对象,但是p2a的类型是Object而非Point类型:
Object p2a = p2;
现在我们重复第一个比较,但是不再使用p2而是p2a,我们将会得到如下的结果:
System.out.println(p1.equals(p2a)); // prints false
到底是那里出了了问题?事实上,之前所给出的equals版本并没有覆盖Object类的equals方法,因为他的类型不同。下面是Object的equals方法的定义
public boolean equals(Object other)
因为Point类中的equals方法使用的是以Point类而非Object类做为参数,因此它并没有覆盖Object中的equals方法。而是一种变化了的重载。在Java中重载被解析为静态的参数类型而非运行期的类型,因此当静态参数类型是Point,Point的equals方法就被调用。然而当静态参数类型是Object时,Object类的equals就被调用。因为这个方法并没有被覆盖,因此它仍然是实现成比较对象标示。这就是为什么虽然p1和p2a具有同样的x,y值,”p1.equals(p2a)”仍然返回了false。这也是会什么HasSet的contains方法返回 false的原因,因为这个方法操作的是泛型,他调用的是一般化的Object上equals方法而非Point类上变化了的重载方法equals
一个更好但不完美的equals方法定义如下:
// A better definition, but still not perfect
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
result = (this.getX() == that.getX() && this.getY() == that.getY());
}
return result;
}
现在equals有了正确的类型,它使用了一个Object类型的参数和一个返回布尔型的结果。这个方法的实现使用instanceof操作和做了一个造型。它首先检查这个对象是否是一个Point类,如果是,他就比较两个点的坐标并返回结果,否则返回false。
陷阱2:重载了equals的但没有同时重载hashCode的方法
如果你使用上一个定义的Point类进行p1和p2a的反复比较,你都会得到你预期的true的结果。但是如果你将这个类对象放入到HashSet.contains()方法中测试,你就有可能仍然得到false的结果:
Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
HashSet<Point> coll = new HashSet<Point>();
coll.add(p1);
System.out.println(coll.contains(p2)); // 打印 false (有可能)
事实上,这个个结果不是100%的false,你也可能有返回ture的经历。如果你得到的结果是true的话,那么你试试其他的坐标值,最终你一定会得到一个在集合中不包含的结果。导致这个结果的原因是Point重载了equals却没有重载hashCode。
注意上面例子的的容器是一个HashSet,这就意味着容器中的元素根据他们的哈希码被被放入到”哈希桶 hash buckets”中。contains方法首先根据哈希码在哈希桶中查找,然后让桶中的所有元素和所给的参数进行比较。现在,虽然最后一个Point类的版本重定义了equals方法,但是它并没有同时重定义hashCode。因此,hashCode仍然是Object类的那个版本,即:所分配对象的一个地址的变换。所以p1和p2的哈希码理所当然的不同了,甚至是即时这两个点的坐标完全相同。不同的哈希码导致他们具有极高的可能性被放入到集合中不同的哈希桶中。contains方法将会去找p2的哈希码对应哈希桶中的匹配元素。但是大多数情况下,p1一定是在另外一个桶中,因此,p2永远找不到p1进行匹配。当然p2和p2也可能偶尔会被放入到一个桶中,在这种情况下,contains的结果就为true了。
最新一个Point类实现的问题是,它的实现违背了作为Object类的定义的hashCode的语义。
如果两个对象根据equals(Object)方法是相等的,那么在这两个对象上调用hashCode方法应该产生同样的值
事实上,在Java中,hashCode和equals需要一起被重定义是众所周知的。此外,hashCode只可以依赖于equals依赖的域来产生值。对于Point这个类来说,下面的的hashCode定义是一个非常合适的定义。
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
result = (this.getX() == that.getX() && this.getY() == that.getY());
}
return result;
}
@Override public int hashCode() {
return (41 * (41 + getX()) + getY());
}
}
这只是hashCode一个可能的实现。x域加上常量41后的结果再乘与41并将结果在加上y域的值。这样做就可以以低成本的运行时间和低成本代码大小得到一个哈希码的合理的分布(译者注:性价比相对较高的做法)。
增加hashCode方法重载修正了定义类似Point类等价性的问题。然而,关于类的等价性仍然有其他的问题点待发现。
陷阱3:建立在会变化字段上的equals定义
让我们在Point类做一个非常微小的变化
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) { // Problematic
this.x = x;
}
public void setY(int y) {
this.y = y;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
result = (this.getX() == that.getX() && this.getY() == that.getY());
}
return result;
}
@Override public int hashCode() {
return (41 * (41 + getX()) + getY());
}
}
唯一的不同是x和y域不再是final,并且两个set方法被增加到类中来,并允许客户改变x和y的值。equals和hashCode这个方法的定义现在是基于在这两个会发生变化的域上,因此当他们的域的值改变时,结果也就跟着改变。因此一旦你将这个point对象放入到集合中你将会看到非常神奇的效果。
Point p = new Point(1, 2);
HashSet<Point> coll = new HashSet<Point>();
coll.add(p);
System.out.println(coll.contains(p)); // 打印 true
现在如果你改变p中的一个域,这个集合中还会包含point吗,我们将拭目以待。
p.setX(p.getX() + 1);
System.out.println(coll.contains(p)); // (有可能)打印 false
看起来非常的奇怪。p去那里去了?如果你通过集合的迭代器来检查p是否包含,你将会得到更奇怪的结果。
Iterator<Point> it = coll.iterator();
boolean containedP = false;
while (it.hasNext()) {
Point nextP = it.next();
if (nextP.equals(p)) {
containedP = true;
break;
}
}
System.out.println(containedP); // 打印 true
结果是,集合中不包含p,但是p在集合的元素中!到底发生了什么!当然,所有的这一切都是在x域的修改后才发生的,p最终的的hashCode是在集合coll错误的哈希桶中。即,原始哈希桶不再有其新值对应的哈希码。换句话说,p已经在集合coll的是视野范围之外,虽然他仍然属于coll的元素。
从这个例子所得到的教训是,当equals和hashCode依赖于会变化的状态时,那么就会给用户带来问题。如果这样的对象被放入到集合中,用户必须小心,不要修改这些这些对象所依赖的状态,这是一个小陷阱。如果你需要根据对象当前的状态进行比较的话,你应该不要再重定义equals,应该起其他的方法名字而不是equals。对于我们的Point类的最后的定义,我们最好省略掉hashCode的重载,并将比较的方法名命名为 equalsContents,或其他不同于equals的名字。那么Point将会继承原来默认的equals和hashCode的实现,因此当我们修改了x域后p依然会呆在其原来在容器中应该在位置。
陷阱4:不满足等价关系的equals错误定义
Object中的equals的规范阐述了equals方法必须实现在非null对象上的等价关系:
* 自反原则:对于任何非null值X,表达式x.equals(x)总返回true。
* 等价性:对于任何非空值x和y,那么当且仅当y.equals(x)返回真时,x.equals(y)返回真。
* 传递性:对于任何非空值x,y,和z,如果x.equals(y)返回真,且y.equals(z)也返回真,那么x.equals(z)也应该返回真。
* 一致性:对于非空x,y,多次调用x.equals(y)应该一致的返回真或假。提供给equals方法比较使用的信息不应该包含改过的信息。
* 对于任何非空值x,x.equals(null)应该总返回false.
Point类的equals定义已经被开发成了足够满足equals规范的定义。然而,当考虑到继承的时候,事情就开始变得非常复杂起来。比如说有一个Point的子类ColoredPoint,它比Point多增加了一个类型是Color的color域。假设Color被定义为一个枚举类型:
public enum Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;
}
ColoredPoint重载了equals方法,并考虑到新加入color域,代码如下:
public class ColoredPoint extends Point { // Problem: equals not symmetric
private final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof ColoredPoint) {
ColoredPoint that = (ColoredPoint) other;
result = (this.color.equals(that.color) && super.equals(that));
}
return result;
}
}
这是很多程序员都有可能写成的代码。注意在本例中,类ColoredPointed不需要重载hashCode,因为新的ColoredPoint 类上的equals定义,严格的重载了Point上equals的定义。hashCode的规范仍然是有效,如果两个着色点(colored point)相等,其坐标必定相等,因此它的hashCode也保证了具有同样的值。
对于ColoredPoint类自身对象的比较是没有问题的,但是如果使用ColoredPoint和Point混合进行比较就要出现问题。
Point p = new Point(1, 2);
ColoredPoint cp = new ColoredPoint(1, 2, Color.RED);
System.out.println(p.equals(cp)); // 打印真 true
System.out.println(cp.equals(p)); // 打印假 false
“p等价于cp”的比较这个调用的是定义在Point类上的equals方法。这个方法只考虑两个点的坐标。因此比较返回真。在另外一方面,“cp 等价于p”的比较这个调用的是定义在ColoredPoint类上的equals方法,返回的结果却是false,这是因为p不是 ColoredPoint,所以equals这个定义违背了对称性。
违背对称性对于集合来说将导致不可以预期的后果,例如:
Set<Point> hashSet1 = new java.util.HashSet<Point>();
hashSet1.add(p);
System.out.println(hashSet1.contains(cp)); // 打印 false
Set<Point> hashSet2 = new java.util.HashSet<Point>();
hashSet2.add(cp);
System.out.println(hashSet2.contains(p)); // 打印 true
因此虽然p和cp是等价的,但是contains测试中一个返回成功,另外一个却返回失败。
你如何修改equals的定义,才能使得这个方法满足对称性?本质上说有两种方法,你可以使得这种关系变得更一般化或更严格。更一般化的意思是这一对对象,a和b,被用于进行对比,无论是a比b还是b比a 都返回true,下面是代码:
public class ColoredPoint extends Point { // Problem: equals not transitive
private final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof ColoredPoint) {
ColoredPoint that = (ColoredPoint) other;
result = (this.color.equals(that.color) && super.equals(that));
}
else if (other instanceof Point) {
Point that = (Point) other;
result = that.equals(this);
}
return result;
}
}
在ColoredPoint中的equals的新定义比老定义中检查了更多的情况:如果对象是一个Point对象而不是ColoredPoint,方法就转变为Point类的equals方法调用。这个所希望达到的效果就是equals的对称性,不管”cp.equals(p)”还是”p.equals(cp)”的结果都是true。然而这种方法,equals的规范还是被破坏了,现在的问题是这个新等价性不满足传递性。考虑下面的一段代码实例,定义了一个点和这个点上上两种不同颜色点:
ColoredPoint redP = new ColoredPoint(1, 2, Color.RED);
ColoredPoint blueP = new ColoredPoint(1, 2, Color.BLUE);
redP等价于p,p等价于blueP
System.out.println(redP.equals(p)); // prints true
System.out.println(p.equals(blueP)); // prints true
然而,对比redP和blueP的结果是false:
System.out.println(redP.equals(blueP)); // 打印 false
因此,equals的传递性就被违背了。
使equals的关系更一般化似乎会将我们带入到死胡同。我们应该采用更严格化的方法。一种更严格化的equals方法是认为不同类的对象是不同的。这个可以通过修改Point类和ColoredPoint类的equals方法来达到。你能增加额外的比较来检查是否运行态的这个Point类和那个Point类是同一个类,就像如下所示的代码一样:
// A technically valid, but unsatisfying, equals method
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
result = (this.getX() == that.getX() && this.getY() == that.getY()
&& this.getClass().equals(that.getClass()));
}
return result;
}
@Override public int hashCode() {
return (41 * (41 + getX()) + getY());
}
}
你现在可以将ColoredPoint类的equals实现用回刚才那个不满足对称性要的equals实现了。
public class ColoredPoint extends Point { // 不再违反对称性需求
private final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof ColoredPoint) {
ColoredPoint that = (ColoredPoint) other;
result = (this.color.equals(that.color) && super.equals(that));
}
return result;
}
}
这里,Point类的实例只有当和另外一个对象是同样类,并且有同样的坐标时候,他们才被认为是相等的,即意味着 .getClass()返回的是同样的值。这个新定义的等价关系满足了对称性和传递性因为对于比较对象是不同的类时结果总是false。所以着色点 (colored point)永远不会等于点(point)。通常这看起来非常合理,但是这里也存在着另外一种争论——这样的比较过于严格了。
考虑我们如下这种稍微的迂回的方式来定义我们的坐标点(1,2)
Point pAnon = new Point(1, 1) {
@Override public int getY() {
return 2;
}
};
pAnon等于p吗?答案是假,因为p和pAnon的java.lang.Class对象不同。p是Point,而pAnon是Point的一个匿名派生类。但是,非常清晰的是pAnon的确是在坐标1,2上的另外一个点。所以将他们认为是不同的点是没有理由的。
canEqual 方法
到此,我们看其来似乎是遇到阻碍了,存在着一种正常的方式不仅可以在不同类继承层次上定义等价性,并且保证其等价的规范性吗?事实上,的确存在这样的一种方法,但是这就要求除了重定义equals和hashCode外还要另外的定义一个方法。基本思路就是在重载equals(和hashCode)的同时,它应该也要要明确的声明这个类的对象永远不等价于其他的实现了不同等价方法的超类的对象。为了达到这个目标,我们对每一个重载了equals的类新增一个方法canEqual方法。这个方法的方法签名是:
public boolean canEqual(Object other)
如果other 对象是canEquals(重)定义那个类的实例时,那么这个方法应该返回真,否则返回false。这个方法由equals方法调用,并保证了两个对象是可以相互比较的。下面Point类的新的也是最终的实现:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
result =(that.canEqual(this) && this.getX() == that.getX() && this.getY() == that.getY());
}
return result;
}
@Override public int hashCode() {
return (41 * (41 + getX()) + getY());
}
public boolean canEqual(Object other) {
return (other instanceof Point);
}
}
这个版本的Point类的equals方法中包含了一个额外的需求,通过canEquals方法来决定另外一个对象是否是是满足可以比较的对象。在Point中的canEqual宣称了所有的Point类实例都能被比较。
下面是ColoredPoint相应的实现
public class ColoredPoint extends Point { // 不再违背对称性
private final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
@Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof ColoredPoint) {
ColoredPoint that = (ColoredPoint) other;
result = (that.canEqual(this) && this.color.equals(that.color) && super.equals(that));
}
return result;
}
@Override public int hashCode() {
return (41 * super.hashCode() + color.hashCode());
}
@Override public boolean canEqual(Object other) {
return (other instanceof ColoredPoint);
}
}
在上显示的新版本的Point类和ColoredPoint类定义保证了等价的规范。等价是对称和可传递的。比较一个Point和 ColoredPoint类总是返回false。因为点p和着色点cp,“p.equals(cp)返回的是假。并且,因为cp.canEqual(p) 总返回false。相反的比较,cp.equals(p)同样也返回false,由于p不是一个ColoredPoint,所以在 ColoredPoint的equals方法体内的第一个instanceof检查就失败了。
另外一个方面,不同的Point子类的实例却是可以比较的,同样没有重定义等价性方法的类也是可以比较的。对于这个新类的定义,p和pAnon的比较将总返回true。下面是一些例子:
Point p = new Point(1, 2);
ColoredPoint cp = new ColoredPoint(1, 2, Color.INDIGO);
Point pAnon = new Point(1, 1) {
@Override public int getY() {
return 2;
}
};
Set<Point> coll = new java.util.HashSet<Point>();
coll.add(p);
System.out.println(coll.contains(p)); // 打印 true
System.out.println(coll.contains(cp)); // 打印 false
System.out.println(coll.contains(pAnon)); // 打印 true
这些例子显示了如果父类在equals的实现定义并调用了canEquals,那么开发人员实现的子类就能决定这个子类是否可以和它父类的实例进行比较。例如ColoredPoint,因为它以”一个着色点永远不可以等于普通不带颜色的点重载了” canEqual,所以他们就不能比较。但是因为pAnon引用的匿名子类没有重载canEqual,因此它的实例就可以和Point的实例进行对比。
canEqual方法的一个潜在的争论是它是否违背了Liskov替换准则(LSP)。例如,通过比较运行态的类来实现的比较技术(译者注: canEqual的前一版本,使用.getClass()的那个版本),将导致不能定义出一个子类,这个子类的实例可以和其父类进行比较,因此就违背了 LSP。这是因为,LSP原则是这样的,在任何你能使用父类的地方你都可以使用子类去替换它。在之前例子中,虽然cp的x,y坐标匹配那些在集合中的点,然而”coll.contains(cp)”仍然返回false,这看起来似乎违背得了LSP准则,因为你不能这里能使用Point的地方使用一个 ColoredPointed。但是我们认为这种解释是错误的,因为LSP原则并没有要求子类和父类的行为一致,而仅要求其行为能一种方式满足父类的规范。
通过比较运行态的类来编写equals方法(译者注: canEqual的前一版本,使用.getClass()的那个版本)的问题并不是违背LSP准则的问题,但是它也没有为你指明一种创建派生类的实例能和父类实例进行对比的的方法。例如,我们使用这种运行态比较的技术在之前的”coll.contains(pAnon)”将会返回false,并且这并不是我们希望的。相反我们希望“coll.contains(cp)”返回false,因为通过在ColoredPoint中重载的equals,我基本上可以说,一个在坐标1,2上着色点和一个坐标1,2上的普通点并不是一回事。然而,在最后的例子中,我们能传递Point两种不同的子类实例到集合中 contains方法,并且我们能得到两个不同的答案,并且这两个答案都正确。
•使用字符串缓冲区而不是字符串连接,当进行连续字符串操作时要避免不必要地创建那些最终必须经过垃圾回收的对象。
•避免连续写入 Java 控制台以减少字符串操作、文本格式化以及输出的花费。
•必要时通过使用变量的原语类型来避免对象创建和操作的花费。
•经常高速缓存用过的对象以减少必须的垃圾回收数量,并且避免重复创建对象的需求。
•尽可能分组本地操作以减少 Java 本地接口(JNI)的调用。
•只有在必要时再使用同步方法,以此限制在 JVM 和操作系统中的多任务。
•除非必要避免调用垃圾回收器。如果您必须调用它,只有在空闲时间或一些非关键阶段再这样做。
•可能时使用整型而不是长整型,因为 32 位操作快于 64 位。
•可能时申明方法为 final。JVM 处理 final 的方法较好。
•当创建常量时为了减少变量需要初始化的次数,使用关键字 static final。
•避免不必要的“casts”和“instanceof”引用,因为在 Java 中销毁操作不是在编译时而是在运行时执行的。
•当数组可以满足要求时尽可能避免使用向量。
•从向量末端添加和删除项以得到较高性能。
•避免在循环中分配对象。
•使用缓冲区 I/O 并调优缓冲区大小。
•使用连接池和准备缓存声明进行数据库访问。
•使用连接池连接到数据库并重用连接而不是重复打开和关闭连接。
•最大化线程生存期并最小化线程创建和销毁循环。
•最小化共享资源的争用。
•最小化短生存期对象的创建。
•避免远程方法调用。
•使用回调以避免阻塞远程方法调用。
•避免创建只用来访问一个方法的对象。
•尽可能保持同步方法处于循环外。
•在数据库中以 Unicode 形式存储字符串和字符数据。
•记录 CLASSPATH 以便最常用的库先出现。
Analytics Plugin created by Web Hosting