2012年7月12日星期四

AirPlay


我接触Airplay差不多一个星期,时间不长,我觉得Airplay是一款非常优秀的播放器,虽然有的地方还有待改进和完善,我真诚地希望Airplay越来越好。下面,我就说说我个人对Airplay的一些感受和建议:
1、为何会用Airplay
最初我是千千静听用户,后来不太喜欢千千静听渲染偏重,音色偏暖,而且它的自动升级和弹窗太讨厌。自动升级不知怎么和百度什么插件扯上关系了,还在系统盘创建baidu之类的目录;弹窗没有错,毕竟是免费软件,但弹窗内容比较低俗,而且总是在音乐播放中途弹出来,严重影响听音乐的心情。
后来就改用foobar了,感觉foobar对声音的渲染较少,比千千好,但是这播放器的默认界面难以让人接受,所以都是用别人的界面配置。别人的东西毕竟是很个性化的,不能完全满足我的口味和需要,我也不爱折腾,懒得去学这些东西。另外,歌词功能一直都是foobar的软肋,尽管通过插件和外挂软件能能够实现歌词功能,但我还是不太满意。
前几天,在360软件管家里发现Airplay,就下载下来用了几天。Airplay给我的感觉是麻雀虽小五脏俱全,界面很漂亮、简单易用,音质不错,有歌词和图片功能,这些正是我需要的,所以我还会继续用Airplay。
2、Airplay的用户群
我觉得Airplay的定位很好,能够满足很广泛的用户群。首先,Airplay支持在线播放,独有的秒听技术即点即播,满足那些喜欢在线听歌的群体;其次,本地播放功能界面友好,简单易用,音质不俗,满足了喜欢本地播放,对音质又有较高要求的群体。但是,像音乐发烧友这类群体可能Airplay无法满足他们,因为这类群体乐于DIY,更热衷于foobar高度的自由化和丰富强大的插件功能。
3、Airplay的音质
对于通常是播放本地音乐,特别是播放无损音乐的用户,他们可能最看重的还是播放器本身的音质及对音乐本身的还原性。下面我说说我自己的听感,我不是什么音乐发烧友,我音箱用惠威M100,声卡就是技嘉780板载的,用千千静听、foobar和Airplay对比播放wav格式的无损音乐,就音质来讲,我感觉不出明显差别,在音色上,千千静听音色偏暖,foobar的高频部分更亮丽,Airplay的声音更加平实自然。
4、Airplay的在线播放和本地播放
Airplay能够同时满足在线播放和本地播放,但是会存在这样一种情况,那就是那些只需要本地播放的用户其实是不想看到与在线播放相关的东西的,相反那些只需要在线播放的用户可能也不想看到与本地播放相关的东西,因为自己根本用不到的东西放在那里就是多余的。当然,把Airplay做成在线播放和本地播放两个版本不太现实。我觉得可以将在线播放和本地播放做成两个模块,在软件安装的时候可以由用户自行选择,但是Airplay只是个单文件程序,我不知道这样是否可行。如果这样不可行的话,能够在播放器里通过设置完全隐藏掉在线播放或者本地播放也是一种办法,可能实现起来更容易些。就目前的版本来说,仅仅是播放列表那里还无法完全隐藏在线或者本地播放。
5、Airplay没有打开文件按钮
如果想要在Airplay界面里打开音乐文件只能在本地播放列表通过添加文件的方式打开,而且多次添加文件的话,前几次添加的文件是不会自动清除的。没有打开文件按钮不太方便哦。
6、Airplay播放列表的搜索功能
目前版本的Airplay播放列表的搜索功能只能搜索歌曲名称,不支持歌手名字的搜索。有很多时候其实是需要搜索某一个歌手的所有歌曲,而不是仅仅找一首歌。
7、Airplay的图片显示功能
有些用户的硬盘上可能有大量本地专辑封面和艺人图片,而目前版本的Airplay只能自动搜索在线图片,而有些专辑和艺人的图片服务器上并不一定有,如果用户想要自己将本地图片与歌曲关联,只能一个一个地关联,不支持批量关联。有些歌曲是同一张专辑里的,或者同一个歌手的,但是不能批量关联图片,这样是很繁琐的。我觉得最好是给图片搜索定义“本地搜索→网络搜索”这样的规则,通过歌曲标签的专辑或歌手优先与本地图片关联。
8、Airplay的歌曲标签功能
目前的Airplay歌曲标签过于简单,仅有歌曲名称、歌手、专辑这三项,而且也不支持标签的批量修改,像歌曲码率之类的文件信息也无法查看。
9、Airplay的cue双向识别功能
这个功能我认为是相当牛逼的,只要有相应的cue文件,即使打开整轨文件也能分轨播放,但是,我认为如果Airplay不引入媒体库功能的话,那将是对这个功能的最大浪费。Foobar的媒体库功能算蛮强大的,但是它不支持cue双向识别,通常的做法是把cue文件一个一个地内嵌到相应整轨文件中,然后排除掉媒体库对cue文件的监视,此外悲剧的是wav格式是不能内嵌cue的。Airplay的cue双向识别却能够轻松解决这些问题,如果再加上完善的歌曲标签功能,可想而知Airplay的媒体库功该有多么强大。
10、Airplay最小化到系统托盘
在设置当中如果勾选“最小化到系统托盘”, Airplay将不会显示在任务栏,即使没有点击最小化按钮,这样对拖曳操作是很不方便的啊。不知是目前版本的bug还是开发人员疏忽了,“最小化到系统托盘”的意思应该是点击最小化按钮后,Airplay才不在任务栏显示,不点击最小化按钮的话,任务栏还是应该显示Airplay的啊。
11、Airplay是否会加入可视化效果
可视化效果如果能够加入的话当然最好,能够给播放器本身静止的界面带来些动感。
12、Airplay是否会加入桌面歌词
我想这个功能还是蛮多人需要的吧。
目前就这些吧。我知道开发组人员非常辛苦,一款软件也难以满足所有人的需求,我只是想把我作为一个普通用户对Airplay的感受反馈给开发组,希望所帮助,说的不对的地方还请包涵啊,真心地希望Airplay越来越好。

2012年7月9日星期一


              小心,你的文件正在被迅雷盗窃!


一:前言用迅雷时,哪怕什么下载都不开,上传也都关掉,网速还是慢得可怜。一看任务管理器,网络正在全负荷运转。到底是为什么呢? 本文介绍了我是如何找出迅雷“盗窃”活动的蛛丝马迹,并估计了迅雷的这种暗箱操作会给我们用户带来哪些损失和潜在危险。最后,本文提出了一些有效的对策。 本文的内容对于使用其他下载软件的人也是很有价值的,为了你爱机的安全和隐私,值得一读。
声明:本文所指的迅雷是指迅雷5.6.5.15版。

二:形迹可疑!
用迅雷时,哪怕什么下载都不开,上传也都关掉,网速还是慢得可怜。一看任务管理器,网络正在全负荷运转。到底是为什么呢?我始终不得其解。后来搞到了一个软件,才揭开了迅雷的卑劣的真面目。

下面隆重推出免费软件 Process Monitor v1.26(1.1MB)
http://technet.microsoft.com/zh-cn/sysinternals/bb896645(en-us).aspx
http://download.sysinternals.com/Files/ProcessMonitor.zip

这是一个微软技术支持网络推荐的小工具,正是凭借他的全面监视功能,我才发现了迅雷背着用户干的“好事”。你可以用一下Process Monitor,用亲自尝试和自己的判断来评价迅雷的所作所为。

三:你还敢抵赖?!
运行Process Monitor,设定只显示Thunder.exe(迅雷主程序)的文件操作行为。迅雷干了些什么事情就一目了然了。
 

图一:迅雷一运行就把所有硬盘中的所有目录全部扫描一遍。

迅雷在扫描目录时,只对比较大的文件感兴趣,因为bt下载的都是大文件。
 
图二:找到热门的bt就开始盗窃。

一旦有文件夹的名字和某个热门bt相符,迅雷就认定这是有用的资源开始大量盗窃。
 
图三:迅雷正在疯狂盗窃,频繁地读取硬盘。

我 们知道,一个程序如果要读取某个文件,就必须把这个文件设成独享。那么这时候我们如果要移动、删除这个文件,系统就会有错误提示。这样行迹就败露了。为了 避免这种情况,迅雷每秒钟打开关闭文件十几次,这样就能神不知鬼不觉。但是这样对于硬盘的损坏是其他同类软件的十几倍。为了一己之私,把用户的硬盘置于不 顾,迅雷!你于心何忍?!
 
图四:网速几乎消耗殆尽,难怪网页打开变得很慢。

迅 雷这样做的不可告人的目的是什么呢?显然是要把你的文件传给其他人。而且是其他用迅雷的人,不会传给用bitcomet,快车等其他工具的人(否则岂不是 义务劳动了)。这样,在下载热门种子时用迅雷的速度就比其他软件快,提高了迅雷的口碑。而下载冷门种子迅雷就没有什么优势,原因就在这里。

四:这有什么危害呢?
据我分析,这种盗窃对于我们有四大危害:
1硬盘容易损坏  2网速大量被占  3无法管理上传  4隐私容易泄漏
1:硬盘容易损坏。
前面已经说了,为了不被发现,迅雷就不把我们硬盘寿命放在眼里。所谓硬盘缓存等措施也形同虚设。硬盘在你不知不觉中慢慢老去。

2: 网速大量被占。
热门种子的上传速度很容易撑满全部带宽。你上网就只好悠着点了!

3:无法管理上传。
比如你想把一个冷门种子给大家分享,于是把一个热门种子的上传关掉。
但是这个上传其实关不掉的!于是热门种子占据了大多数上传速度,你想上传的东西只有10几k/秒。用户完全失去了设置的权利,不知这电脑是归我管还是归迅雷管。

4:隐私容易泄漏
迅 雷盗窃的是热门bt内容,应该说对于我们的隐私不会有什么危险,不过也不一定。如果有一个黑客想偷看别人电脑里的照片。大家常常有photo这个文件夹。 于是他弄一个叫photo的bt,再用几百台电脑把它伪装成一个热门bt,这样迅雷就会主动把别人电脑中凡是photo文件夹里的文件全部拿出来给他的。

五:我们的补救措施,魔高一尺,道高一丈!根据反复试验,发现迅雷是按照文件夹名而不是torrent文件来找到热门bt文件。
我们知道,bt下载时往往要单独新建一个文件夹,文件夹有个默认的名字。比如bbs.wofei.net@越狱第二季第1-22集全  迅雷正是抓住这个来找到他要的东西。
那么我们就把 "bbs.wofei.net@越狱第二季第1-22集全" 随便改成 "a1_bbs.wofei.net@越狱第二季第1-22集全"(随便改的),迅雷就找不到了!
 
图五:看你还能兴风作浪!
 
图六:网速马上降下来了,立竿见影。

六:最后的一点废话。
其实到这里,我们已经能够应付迅雷的盗窃了。如果你认为不必再深究,事不关己,高高挂起,那就不用再读下去了。

我们知道,bt的精神就在于分享。没有别人的上传,哪有你的下载?但是bt也讲究自愿。当你享受着高速下载时,不知有没有想过,你的数据可能是在别人不知情的情况下得到的?如果是这样,你还能心安理得的下载吗?
而且迅雷的这种行为使得我们无法管理bt,想上传的不让传,不想传的占了网速。迅雷的这种行为是何等霸道!何等猖狂!我们又是何等无奈!

难道做软件可以只顾利益不顾道德吗?
难道可以只顾网速不顾硬盘吗?
难道可以只顾让别人下载不顾我浏览网页吗?

但 是话又说回来,佛曰:放下屠刀,立地成佛。只要迅雷公司稍微改一下程序,尊重一些用户,就还是一个好软件。佛又曰:善恶全在一念之间,如果迅雷变本加厉, 以后不光是偷热门bt了,什么都偷,做出更出格的事情,那么它被用户唾弃也就指日可待了。毕竟我们网民不是好惹的,忍耐度是有限的!

农历新年马上就要到了,我在这里问候全体迅雷的开发人员,向他们表示诚挚的问候和节日的祝愿,希望他们在春节假期中好好反省一下,节后推出一个尊重用户的新版迅雷!

大家有什么看法?迅雷在这方面的口碑好像越来越差了!!

投递者加注语:

联想到迅雷的“等级制度”以及“全球排名”,每天挂机几小时+下载10个文件,似乎正是为了上文所言的“非法行为”制造机会。这种行为无疑是损害使用者的利 益的。无论你是否支持迅雷,或者是否支持其他下载软件,亦或者是坚决的反“枪手”主义者,还是彻底的批判一切的志士,对于这一篇用事实说话的文章(我转载 来的),是否有事吗话要说呢?是否有什么想法呢?即便你完全支持迅雷,是一个迅雷的坚决的捍卫者,那么对于你渐渐“老去”的磁盘,你难道没有心疼?

我是一个中间立场者,本人电脑中安装有4个下载软件(非电驴和非BT的下载工具),得出的结论,的确在使用Thunder的时候,打开网页的速度严重 受到影响(512K上海电信,在这里BS一下电信。。。),所以现在本人下载什么都是使用Theworld内置的下载工具。

听说Maxthon与迅雷合作,在Maxthon内也置入了下载器,不知道现在的Maxthon下载器是否也像迅雷那样,行上文所述之举呢,我期待着大家的体会和观点。

2012年6月19日星期二

为什么中国人宁花4000买手机 不花6元买游戏


网易游戏频道做了一个有意思的专题:“宁花4000买手机 不花6元买游戏”,来讨论中国iOS游戏市场上的怪现象。中国大陆已成为iPhone全球销量排名第二的地区,仅次于美国。而与硬件的热销形成对比,中国大陆的iOS应用市场的规模,仅占全球市场的3%。
  曾经毁了中国PC游戏市场的那些东西,如今又在iOS游戏市场一一重现:盗版、外挂、抄袭、强制消费、恶意竞争……这是整个中国游戏业的一个缩影。全球有10%的iPhone进行过“越狱”,而在中国,这一比例高达60%,这里最奇怪的一个问题是,为什么中国人会花费4000元以上来购买iPhone手机,却不肯花6元钱买游戏?
  游戏的价格是否合理?
  早期电脑上的盗版游戏大多是通过盗版光盘来销售,一张盗版游戏的价格也在5元、10元左右,其价位和目前主流iOS游戏大体一致。得益于iOS低廉的销售发布渠道,iPhone游戏的价格大多是0.99美元(6元人民币),一些游戏“大作”价格会高一些,但也少见超过9.99美元(60元人民币)。其总体价格可以说比较符合中国人的消费水平,早先购买盗版光盘的游戏用户应该不会认为这个价格会较高。
  观念的落伍?
  买得起iPhone应该不算是低收入人群,不买应用有很大可能是没观念,在中国人心中,与硬件相比,软件不值得尊重。中国人花60元购买iPhone贴膜不会有任何问题,但用来购买10个游戏却会觉得价格高,这也是常年盗版环境下的惯性思维,在一个漠视知识产权的国度,看不见、摸不着的“软件”是没有价值的。
  用户使用水平过低?
  还有一种可能,就是用户的使用操作水平过低,不会安装应用。很多人只是将iPhone当做一个4000元的电话,只是使用其电话功能,而不会或不懂如何安装应用。这部分用户应该并不多,iPhone的使用界面已经足够简单易用了,稍稍学习一下的话,用户应该可以学会如何进行应用的购买。
  iPhone对于中国用户的体验不佳?
  从另一方面上讲,苹果iPhone在中国的越狱率很高,也和苹果本身不重视中国市场有关,举一个最简单的例子:“拼音输入法”,在iPhone里面,繁体输入法中有台湾流行的“仓颉输入法”,可见苹果是可以将一些本地流行的输入法整合到iOS中,但iOS至今没有整合那怕一个中国大陆流行的输入法,而苹果自己的中文拼音输入法到底有多烂,恐怕大家都深有体会,百度拼音、搜狗拼音、腾讯拼音等任何一个输入法都比苹果的强。
  另一个本地化功能是“来电归属地”问题,这对于饱受垃圾短信和电话骚扰的中国用户来说,是一个非常重要的功能,苹果不但自己不提供,还不开放接口让第三方开发商提供。
  对于中国用户来说,这两个功能只有越狱之后才能使用,既然越狱之后iPhone的使用体验能大幅提高,那为什么不越呢?这就是中国特色。
  可见中国地区越狱率极高的原因,苹果自身也难咎其责,如果苹果公司能稍微重视一下中国用户,改善一下其烂到极点的中文输入法,内置一个“来电归属地”功能,估计大部分中国用户就不会越狱了,越狱也是技术活,谁愿意没事瞎折腾啊。

当然还有中国人民的聪明才智,原来的系统,游戏,等等都是在等网上的盗版出来才体验的,听说在国外用盗版是受到鄙视的,不知是不是真的哈?中国人善于改别人的东西,而且还是外表的东西,没有一些实质的东西。也就是没有创造性思维,但是创造性思维又是来自模仿,哈哈自己说的哦

Game


import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import java.util.Timer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Catch_Me extends JFrame implements Runnable
{
    Random R=new Random();
    Random RR=new Random();
ImageIcon bird_img = new ImageIcon("03.gif");//小鼠图片
ImageIcon mouse_img = new ImageIcon("07.gif");//老猫图片
ImageIcon milipic = new ImageIcon("star1.gif");//星星图片
ImageIcon sun= new ImageIcon("sunshine_0.png");//太阳图片
ImageIcon dog=new ImageIcon("dog.gif");
ImageIcon bread=new ImageIcon("bread.gif");
ImageIcon bread2=new ImageIcon("bread2.gif");
ImageIcon bread3=new ImageIcon("bread3.gif");
ImageIcon bread4=new ImageIcon("bread4.gif");
ImageIcon bread5=new ImageIcon("bread5.gif");



//图片装载到标签中
JLabel jb_bird = new JLabel(bird_img);
JLabel jb2_mouse = new JLabel(mouse_img);
JLabel mili = new JLabel(milipic);
JLabel sunl = new JLabel(sun);
JLabel dogl=new JLabel(dog);
JLabel breadl=new JLabel(bread);
JLabel breadl2=new JLabel(bread2);
JLabel breadl3=new JLabel(bread3);
JLabel breadl4=new JLabel(bread4);
JLabel breadl5=new JLabel(bread5);
//JButton button=new JButton("再次挑战");
//JLabel buttonlabel=new JLabel(button);
//设置线程是否运行
static boolean isContinue=true;
static boolean noContinue=true;
static int i=0;
static int j=0;
//初始化对象

public Catch_Me() {
setBak(); // 调用背景方法
this.setSize(980, 670);// 设置窗口大小
this.setTitle("小鼠快跑");
//this.setLayout(null);
this.setResizable(false);

this.setLocationRelativeTo(null);
//设置游戏层

JPanel jp = new JPanel();
jp.setOpaque(false);
this.add(breadl);
        this.add(breadl2);
        this.add(breadl3);
        this.add(breadl4);
        this.add(breadl5);
        //this.getContentPane().setLayout(null);


//jp.add(breadl);

jp.add(sunl);
        jp.add(jb_bird);
        jp.add(jb2_mouse);
        jp.add(mili);
        jp.add(dogl);
        //button.setBounds(440,330,75,45);
        //jp.add(button);
this.getContentPane().add(jp);
breadl.setBounds(R.nextInt(960), R.nextInt(640),205,154);
breadl2.setBounds(R.nextInt(960), R.nextInt(640),205,154);
breadl3.setBounds(R.nextInt(960), R.nextInt(640),205,154);
breadl4.setBounds(R.nextInt(960), R.nextInt(640),205,154);
breadl5.setBounds(R.nextInt(960), R.nextInt(640),205,154);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//增加鼠标动作
this.addMouseMotionListener(new MouseMotionListener() {
//增加鼠标移动执行的方法
public void mouseMoved(MouseEvent arg0) {
if (arg0.getY() <=670&& arg0.getX() <=980) {
jb_bird.setLocation(arg0.getX() - 50, arg0.getY() - 80);
}
if((jb_bird.getLocation().x>=mili.getLocation().x-15&&jb_bird.getLocation().x<=mili.getLocation().x+15)&&(jb_bird.getLocation().y>=mili.getLocation().y-15&&jb_bird.getLocation().y<=mili.getLocation().y+15)){
Random rnd = new Random();
Random rnd2=new Random();
mili.setLocation(rnd.nextInt(300)+1, rnd2.nextInt(300)+1);
//jb2_mouse.setLocation(rnd.nextInt(544), rnd2.nextInt(420));
}
}

//吃面包
public void mouseDragged(MouseEvent arg0)
{
                if(Math.abs(arg0.getX()-breadl.getX())<=2||Math.abs(arg0.getY()-breadl.getY())<=2)
                {
                    breadl.setVisible(false);
                    j++;
                   
                }
                if(Math.abs(arg0.getX()-breadl2.getX())<=2||Math.abs(arg0.getY()-breadl2.getY())<=2)
                {
                    breadl2.setVisible(false);
                    j++;
                }
                if(Math.abs(arg0.getX()-breadl3.getX())<=2||Math.abs(arg0.getY()-breadl3.getY())<=2)
                {
                    breadl3.setVisible(false);
                    j++;
                }
                if(Math.abs(arg0.getX()-breadl4.getX())<=2||Math.abs(arg0.getY()-breadl4.getY())<=2)
                {
                    breadl4.setVisible(false);
                    j++;
                }
                if(Math.abs(arg0.getX()-breadl5.getX())<=2||Math.abs(arg0.getY()-breadl5.getY())<=2)
                {
                    breadl5.setVisible(false);
                    j++;
                }
               
}
//鼠标拖拉组件执行的方法

});
this.setVisible(true);
}

//设置背靠图片
public void setBak() {
((JPanel) this.getContentPane()).setOpaque(false);//设置透明度的
ImageIcon img = new ImageIcon("body_bg.jpg"); // 添加图片
JLabel background = new JLabel(img);
//JButton button=new JButton("再次挑战");
//background.add(button);
this.getLayeredPane().add(background, new Integer(Integer.MIN_VALUE));
background.setBounds(0, 0, img.getIconWidth(), img.getIconHeight());
}
//线程开始
public void start() {
   new timetest_noeasy(this);
        Timer timer=new Timer();
        timer.schedule(new timetest_noeasy(this), 15000);
while (noContinue) {
if(isContinue)
{
 
Thread thr = new Thread(this);
try {
 
thr.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
thr.start();

}
}
}
//执行线程
public void run()
{
   this.add(breadl3);
   this.add(breadl4);
   breadl3.setBounds(R.nextInt(960), R.nextInt(640),205,154);
   breadl4.setBounds(R.nextInt(960), R.nextInt(640),205,154);
 
int x = jb_bird.getLocation().x;
int y = jb_bird.getLocation().y;

if(x<490||y>335)
jb2_mouse.setLocation(x, y);
if(y<335||y>490)
dogl.setLocation(x, y);
try {
           Thread.sleep(300);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

if ((jb_bird.getLocation().x == jb2_mouse.getLocation().x
&& jb_bird.getLocation().y == jb2_mouse.getLocation().y)
||(jb_bird.getLocation().x ==dogl.getLocation().x
               && jb_bird.getLocation().y ==dogl.getLocation().y))
{
isContinue=true;
//JOptionPane.showMessageDialog(null, "小鼠被抓住啦!");
final JFrame frame=new JFrame();
       frame.setTitle("提示信息");
     
       JPanel pane=new JPanel();
       JLabel label=new JLabel("小鼠被抓住啦!");
     
       pane.add(label);
            //pane.add(button);
            frame.add(pane);
            frame.setVisible(true);
            frame.setBounds(500, 300,250, 90);
            frame.setLocationRelativeTo(null);
            try
            {
                Thread.sleep(500);
            }
            catch(InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         
            frame.setVisible(false);
     
     
     

i++;

}
}
}








import java.util.TimerTask;


public class timetest_noeasy extends TimerTask
{
    Catch_Me me;
    public timetest_noeasy(Catch_Me catch_Me_Difficult)
    {
        this.me=catch_Me_Difficult;
    }
  public void run()
    {
        me.noContinue=false;
       
    }
}













import javax.swing.JOptionPane;


public class Catch_Me_Main
{
  //main方法
    public static void main(String[] args){
        int j=0;
        Catch_Me c = new Catch_Me();
        c.start();
        j=c.i;
        //JFrame frame=new JFrame(); 
       // frame.setTitle("提示信息");
        
       /* JPanel pane=new JPanel();
        JLabel text=new JLabel("游戏时间到--- ---"+"小鼠被猫捉了"+c.i+"次");
        JLabel text1=new JLabel("再接再厉,下次见");
        JLabel text2=new JLabel("小鼠吃了"+c.j+"个面包");
        pane.add(text);
        pane.add(text2);
        pane.add(text1);*/ 
        JOptionPane.showMessageDialog(null, "游戏时间到,小鼠被猫捉了"+c.i+"次,吃了"+c.j+"个面包","消息",JOptionPane.WARNING_MESSAGE);
       // frame.add(pane);
        //frame.setVisible(true);
        //frame.setBounds(500, 300,250, 90);
        //frame.setLocationRelativeTo(null);
        
    }
}


















2012年5月23日星期三

2012年5月20日星期日

关于IP的那些事儿--- ---请教贴

本人前两天用goagent翻墙过去,查了本机的IP是在美国,这个是毫无疑问的,但是用另外的一个浏览器再次查询的话就又回到本地的IP了,太奇妙了这个问题,难道一个主机可以有两个IP么?这是不是有点儿... ...

java 最基础的东西,经典老帖


对于这个系列里的问题,每个学Java的人都应该搞懂。当然,如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列。内容均来自于CSDN的经典老贴。

问题一:我声明了什么!

String s = "Hello world!";
许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
这个语句声明的是一个指向对象的引用,名为“s”,可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:
String string = s;
我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。
问题二:"=="和equals方法究竟有什么区别?
==操作符专门用来比较变量的值是否相等。比较好理解的一点是:
int a=10;
int b=10;
则a==b将是true。
但不好理解的地方是:
String a=new String("foo");
String b=new String("foo");
则a==b将返回false。
根据前一帖说过,对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是“两个”,它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。诚然,a和b所指的对象,它们的内容都是"foo",应该是“相等”,但是==操作符并不涉及到对象内容的比较。
对象内容的比较,正是equals方法做的事。
看一下Object对象的equals方法是如何实现的:
boolean equals(Object o){
return this==o;
}
Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。
看一下一个极端的类:
Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}
我覆盖了equals方法。这个实现会导致无论Monster实例内容如何,它们之间的比较永远返回true。
所以当你是用equals方法判断对象的内容是否相等,请不要想当然。因为可能你认为相等,而这个类的作者不这样认为,而类的equals方法的实现是由他掌握的。如果你需要使用equals方法,或者使用任何基于散列码的集合(HashSet,HashMap,HashTable),请察看一下java doc以确认这个类的equals逻辑是如何实现的。
问题三:String到底变了没有?
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。请看下列代码:
String s = "Hello";
s = s + " world!";
s所指向的对象是否改变了呢?从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。
问题四:final关键字到底修饰了什么?
final使得被修饰的变量"不变",但是由于对象型变量的本质是“引用”,使得“不变”也有了两种含义:引用本身的不变,和引用指向的对象不变。
引用本身的不变:
final StringBuffer a=new StringBuffer("immutable");
final StringBuffer b=new StringBuffer("not immutable");
a=b;//编译期错误
引用指向的对象不变:
final StringBuffer a=new StringBuffer("immutable");
a.append(" broken!"); //编译通过
可见,final只对引用的“值”(也即它所指向的那个对象的内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化,final是不负责的。这很类似==操作符:==操作符只负责引用的“值”相等,至于这个地址所指向的对象内容是否相等,==操作符是不管的。
理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象,不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改,一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final,意图使得它“永远不变”。其实那是徒劳的。
问题五:到底要怎么样初始化!
本问题讨论变量的初始化,所以先来看一下Java中有哪些种类的变量。
1. 类的属性,或者叫值域
2. 方法里的局部变量
3. 方法的参数
对于第一种变量,Java虚拟机会自动进行初始化。如果给出了初始值,则初始化为该初始值。如果没有给出,则把它初始化为该类型变量的默认初始值。
int类型变量默认初始值为0
float类型变量默认初始值为0.0f
double类型变量默认初始值为0.0
boolean类型变量默认初始值为false
char类型变量默认初始值为0(ASCII码)
long类型变量默认初始值为0
所有对象引用类型变量默认初始值为null,即不指向任何对象。注意数组本身也是对象,所以没有初始化的数组引用在自动初始化后其值也是null。
对于两种不同的类属性,static属性与instance属性,初始化的时机是不同的。instance属性在创建实例的时候初始化,static属性在类加载,也就是第一次用到这个类的时候初始化,对于后来的实例的创建,不再次进行初始化。这个问题会在以后的系列中进行详细讨论。
对于第二种变量,必须明确地进行初始化。如果再没有初始化之前就试图使用它,编译器会抗议。如果初始化的语句在try块中或if块中,也必须要让它在第一次使用前一定能够得到赋值。也就是说,把初始化语句放在只有if块的条件判断语句中编译器也会抗议,因为执行的时候可能不符合if后面的判断条件,如此一来初始化语句就不会被执行了,这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句,就可以通过编译,因为无论如何,总有至少一条初始化语句会被执行,不会发生使用前未被初始化的事情。对于try-catch也是一样,如果只有在try块里才有初始化语句,编译部通过。如果在catch或finally里也有,则可以通过编译。总之,要保证局部变量在使用之前一定被初始化了。所以,一个好的做法是在声明他们的时候就初始化他们,如果不知道要出事化成什么值好,就用上面的默认值吧!
其实第三种变量和第二种本质上是一样的,都是方法中的局部变量。只不过作为参数,肯定是被初始化过的,传入的值就是初始值,所以不需要初始化。
问题六:instanceof是什么东东?
instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子:
String s = "I AM an Object!";
boolean isObject = s instanceof Object;
我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。
instanceof有一些用处。比如我们写了一个处理账单的系统,其中有这样三个类:
public class Bill {//省略细节}
public class PhoneBill extends Bill {//省略细节}
public class GasBill extends Bill {//省略细节}
在处理程序里有一个方法,接受一个Bill类型的对象,计算金额。假设两种账单计算方法不同,而传入的Bill对象可能是两种中的任何一种,所以要用instanceof来判断:
public double calculate(Bill bill) {
if (bill instanceof PhoneBill) {
//计算电话账单
}
if (bill instanceof GasBill) {
//计算燃气账单
}
...
}
这样就可以用一个方法处理两种子类。
然而,这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现,这是面向对象变成应有的做法,避免回到结构化编程模式。只要提供两个名字和返回值都相同,接受参数类型不同的方法就可以了:
public double calculate(PhoneBill bill) {
//计算电话账单
}
public double calculate(GasBill bill) {
//计算燃气账单
}
所以,使用instanceof在绝大多数情况下并不是推荐的做法,应当好好利用多态。

java方向及学习方法
java分成J2ME(移动应用开发),J2SE(桌面应用开发),J2EE(Web企业级应用),所以java并不是单机版的,只是面向对象语言。建议如果学习java体系的话可以这样去学习:
*第一阶段:Java基础,包括java语法,面向对象特征,常见API,集合框架;
*第二阶段:java界面编程,包括AWT,事件机制,SWING,这个部分也可以跳过,用的时候再看都能来及;
*第三阶段:java API:输入输出,多线程,网络编程,反射注解等,java的精华部分;
*第四阶段:数据库SQL基础,包括增删改查操作以及多表查询;
*第五阶段:JDBC编程:包括JDBC原理,JDBC连接库,JDBC API,虽然现在Hibernate比JDBC要方便许多,但是JDBC技术仍然在使用,JDBC思想尤为重要;
*第六阶段:JDBC深入理解高级特性:包括数据库连接池,存储过程,触发器,CRM思想;
*第七阶段:HTML语言学习,包括HTML标签,表单标签以及CSS,这是Web应用开发的基础;
*第八阶段:JavaScript脚本语言,包括javaScript语法和对象,就这两个方面的内容;
*第九阶段:DOM编程,包括DOM原理,常用的DOM元素以及比较重要的DOM编程思想;
*第十阶段:Servlet开发,从此开始踏入java开发的重要一步,包括XML,Tomcat服务器的安装使用操作,HTTP协议简单理解,Servlet API等,这个是java web开发的基础。
*第十一阶段:JSP开发:JSP语法和标签,自定义标签,EL,JSTL库了解以及MVC三层架构的设计模式理念;
*第十二阶段:AJAX开发:AJAX原理,请求响应处理,AJAX开发库;
*第十三阶段:轻量级框架,三大框架之一Struts框架的学习,自此踏入java web开发的精华部分,包括Struts体系架构,各种组件,标签库和扩展性的学习;
*第十四阶段:Hibernate框架学习,三大框架之一,包括检索映射技术,多表查询技术,缓存技术以及性能方面的优化;
*第十五阶段:Spring框架的学习,三大框架之一,包括了IOC,AOP,DataSource,事务,SSH集成以及JPA集成;

*最后呢,还有些java的技术,包括EJB3.0等,可以选择学习,与三大轻量级框架相比,EJB就是当之无愧的重量级了。