java+myeclipse 编程日志

来源:互联网 发布:50而知天命的英文翻译 编辑:程序博客网 时间:2024/06/05 20:00

首先是一些我精挑细选出来的热键:

quick fix: ctrl+1
cancel: ctrl+z
toggle comment: ctrl+/
add block comment: ctrl+shift+/
remove block comment: ctrl+shift+\
add import: ctrl+shift+m
delete line: ctrl+d
find next: ctrl+k
move lines up: alt+up
move lines down: alt+down
go to next member: ctrl+shift+down
go to previous member: ctrl+shift+up
delete next word: ctrl+delete
delete previous word: ctrl+backspace
select enclosing element: alt+shift+up
word completion: ctrl+alt+/

alt+shift+s: source
+r: generate getters and setters

open call hierarchy: ctrl+alt+h
ctrl+q: last edit location
alt+shift+z+6: try-catch block

                                                     

2009.11.10:

本次编程犯了个比较小白的错误,首先声明一点,因为我使用的代码部分是从网上拷贝下来的代码,所以可能没太理解其作者意图,一些java自带的方法由于我之前没用过,所以理解错了它的参数含义,这种理解错误多少还跟粗心,以及项目目标有关。

因为在使用那些方法时需要改写参数内容,所以这时候就出现异常了,调试了很久才发觉是理解错了方法的使用方式。这种事情还是第一次出现,以后要小心了。

顺便说一下,我这里是把File方法看成是使用两个不同的file了,因为本来是打算实现文件另存功能的,所以不小心看错了,以为是把一个存为另一个。

总结:当你不确定某个方法需要的参数到底代表什么含义,或者它最终返回的是什么时,你就应该慎用此方法,而且一旦你决定要去使用它时,就需要结合你原本的意图,有针对性地仔细测试它,看它能不能帮你达成你的目标,并从该过程中发现各种问题,不断改正错误,吸取教训,获得经验。

PS:

public File( parent, child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。

2009.11.11:

光棍节,忽然想总结一下一些容易产生编程错误的地方。

1、一个java文件只能有一个public类,而且此类的名字须与文件名一致。

2、我在netbeans里写了代码,设好了主项目,点运行,老提示没有主方法,仔细检查,有main方法啊!再反复检查发现没写String[] args,杯具了……

3、静态变量和静态方法既可以在类的实例方法中调用,也可以在静态方法中调用。但是,实例变量与实例方法只能通过对象引用来调用。

4、接口:只含常量(public static final)、抽象方法(public abstract),前面那两个括号表示括号内的内容可省略。抽象类:还可以含 变量、具体方法。注:抽象方法不能含有'{'、'}',即 方法体。

5、一个接口,或者抽象类不能创建实例,但却可以作为数据类型来使用。

6、try-catch-finally中的finally可以用来 在程序发生error并将要退出时 做最后的处理。

7、多态、一般性程序设计可能要用到instanceof,这个是个关键字哦!注意以下例子:

有个Shape、Triangle,Shape中有perimeter(),Triangle中也有,但Triangle中还有height(),Triangle继承自Shape。现有如下语句:

Shape shape = new Shape();

Triangle triangle = new Triangle();

shape = triangle;

shape.perimeter();//调用triangle的perimeter();

shape.height();/*此句有语法错误,理由:父类对象的引用(设为a)被赋值为子类对象的引用(设为b)之后,a调用的方法必须在父类中有所定义,若该方法未在子类中被覆盖,则调用的显然是父类中的方法,若子类中已覆盖了它,则调用的是子类中的方法。*/

((Triangle)shape).height();/*强制类型转换之后,引用已很明确,可以直接调用((Triangle)shape)中的方法。*/

上述语句的注释已经解释得很详细,最后还要强调的是在设计时要时刻留意是否遵循面向对象程序设计语言的特性:抽象、封装、继承、多态。

8、最近留意了一下 隐藏, 发现它是针对数据域与静态方法的,所以子类如果想要覆盖父类中的方法时,必须保证与父类方法的参数列表、返回值类型一致。顺便说一下隐藏,即 在子类中,无法隐藏继承自父类的实例方法,但却可以覆盖它,不过,又无法覆盖继承自父类的数据域及静态方法,但却可以隐藏它们。

通过试验可以得知,子类可以通过定义一个与父类中的静态方法同名的方法,参数列表、返回值类型不一定要一致,如果参数列表不一致,那么子类(注意,我这里写的是“类”而非“对象引用”)可以调用两个版本的该方法,其中一个来自父类,但这不能称之为覆盖,因为父类版本的方法还可见,当然也不能说是隐藏,原因同上,应视为方法重载,即 根据不同的参数列表,去调用不同的版本方法。回到刚才那里,如果子类中的这个静态方法与父类版本的参数列表、返回值类型一致,那么就会发生隐藏,即父类版本的不可见了,当然,你还是可以通过super去调用它,在这里,我们会发现,如果参数列表一致,而返回值类型不同,则会被编译器视为override,并提示 试图返回不兼容的返回值类型,从而会发生编译错误。

最后总结一下:

方法重载:不允许参数列表相同的同名方法定义,否则编译器无法知道调用的是哪个。不论是静态方法还是实例方法,都可以进行方法重载。

方法覆盖:子类中的方法如果试图覆盖父类中的,首先,它必须是实例方法,其次它的参数列表、返回值类型均必须与父类中的一致。若参数列表不一致,视为方法重载。

特点:无法通过super去调用旧方法,可以用对象引用去调用,但是必须先初始化对象引用。

隐藏:如果是方法隐藏,则该方法必须是静态方法,而且参数列表、返回值类型均必须与父类的一致,否则可能成为重载(参数列表不一致),或者编译错误(参数列表一致而返回值类型不一致)。此时新方法向下可见,旧方法被隐藏。如果是数据域隐藏,那么同理,旧的被隐藏,新的可用,且向下可见,而当要使用父类中的数据域时则可以通过使用super来引用。我们经过仔细试验可以发现,子类中可以定义一个变量,这个变量与父类中的同名,甚至同类型,甚至同初值,这些情况均视为数据域隐藏,当然在引用父类中的数据域时,若是静态的,则可以通过类名或super来引用,若是实例数据域,则可以通过对象引用来引用。

特点:可以通过super或者直接使用类名去调用旧方法。

在任何情况下,都不允许出现参数列表相同但返回值类型不同的同名方法。

夜深了,肚子好饿,还没洗衣服呢!呜呜呜……

2009.11.12:

发觉自己认识上还有点疏漏。于是总结了一下:

super关键字可以调用父类的构造方法、方法(不论是静态的还是实例的),当然,也可以调用父类的数据域(不论是静态的还是实例的)。上述说法是没有问题的,不过,更确切一点,应该这么说,子类继承自父类,于是继承了父类的数据域、方法,对于这些内容,不论是静态的还是实例的,只要没被隐藏(针对数据域、静态方法而言),或者没被覆盖(针对实例方法而言),那么在子类中完全可以直接调用(当成就是定义在本类中的一样),无需通过super关键字来调用。当然,如果不是在本类及其子类中调用这些数据域或者方法,那么就应该通过类名或对象引用来调用。在实际使用过程中,对于子类对父类的数据域、方法的继承,是需要考虑可见修饰符的,public、protected、package-private、private,这些可见修饰符可见度递减,在来自父类的数据域或者方法如果在子类中不可见,那么,就无法直接调用之。

另外还有几点:

父类的方法若在子类中不可见,则子类中不会发生覆盖该方法的情况,只能视为重新定义了该方法。

final类无法被继承,final变量是常量,final方法无法被覆盖,但可以被重载。

//详见:final方法不能被覆盖,可被重载(方法名相同而参数不同)

子类中发生的方法覆盖不能使方法的可见度变得比父类中的低。

2009.11.13:寒风肆虐,冷雨交织,在夜深人静,众人安眠的时候,我还在学习,不经感叹:杯具!

刚才发现了一个问题,虽然是老生常谈,但是自己居然又犯了!!!!!!

我把string==null与string.equals("")混淆了!前者检查的是引用是否存在,后者检查的是字符串是否为空字符串,作用完全不同!注意:若为空字符串,那么必然存在引用!另外还要经常考虑是否要使用trim(),以帮助处理空格。注意:空字符串不同于空格字符串!当我们处理输入的内容时,如果对 输入的内容为空格串或空串的情况 有特殊处理要求,那么就应该考虑使用a.trim().equals("")来判断!

嗯,另外还想到一个关于设计的问题,我们在设计软件时,往往要考虑分层处理,那么如果在处理某个问题时,代码较多,问题逻辑较复杂,那么在考虑将它归入高层还是低层时,就要好好考虑了,这是一个将问题丢给谁去处理的问题,不同的设计往往侧重点不同,值得深入研究……

2009.11.15:

周末了,昨天参加了软考,由于学期初害怕自己精力不足(要备战六级,要做课程设计,要学JavaEE,还有研究炒股),所以自视过低,只报了程序员考试,当然昨天整个过程下来基本没什么问题,除了下午的时候有些困想睡觉之外,基本上没什么麻烦。今天是周日,生活依旧很杯具。喝点水,敲代码,继续学习,没办法为了做课程设计,“加班加点”。PS:发现冬天敲键盘感觉很爽****************

废话少说,刚才发现几个知识点的遗忘:

局部变量必须初始化,静态方法无法直接调用实例变量。以前没怎么留意,今天终于发现了:原来我把局部变量与实例变量两个概念搞混了。那几次我直接调用实例变量没什么问题,于是想当然地认为实例变量不用初始化。

输入框直接点确定,默认输入的是空字符串,string变量未初始化则初值为null(若为局部变量则必须初始化)。这一点很有用,特别是在经常使用对话框的程序中。还有,最好能对输入的数据进行预检查。

2009.11.15夜:

今天一边编程,一边对程序进行调试,有了一些体会。发现错误可以分为两种,一种是低级错误,例如,可以是自己把‘{’、‘}’位置放错了,另一种则是高级错误,例如,可以是自己的整个算法想错了,无法解决问题,这是很致命的,这种情况往往会发生在算法题目上,比如ACM的题目。

今天下午编程时犯了第一种错误,可是却调试了很久,为什么呢?一方面可以是自己对现有的参考代码不够熟悉,另一方面则是自己对Java语言的掌握还不到位,一些知识点可能自己确实是知道的,但是一旦放到某个具体问题上,与实际算法逻辑结合起来时,一点小小的疏漏就可能造成较大的逻辑错误,而这些显然自己没能留意到。

在某些条件下,问题是很容易发生的,不论你多么不愿意,而另一些时候,它却会故意潜伏下去。一旦问题发生时,就必须进行调试,对于一些不太复杂的程序段,比如没有太多的跳转语句,思路比较好掌握的,它们往往是顺序执行的,那么采用嵌入输出语句来检查是很容易的事情,这样事实上能很快发现错误。

不过,今天一开始,我却在找高级错误,为什么会这样呢,一出错就马上怀疑自己的思路?事实上,自己只不过是将某个‘}’放错了位置而已。后来我总结了一下,可能是自己信心不足,在对待高级语言上所需采取的学习方法是与对待低级语言不同的。对待低级语言,人们往往要寻找低级错误。那么,对待高级语言就去寻找高级错误,这种做法是否合理呢?高级语言可以帮我们做很多事情,但是选择一旦多了,人们就容易选错,或者说无法全面深入地了解它,进而就会失去把握,每当出错时就会怀疑“我是不是又用错了”。我想,如果你是这种语言的作者的话,你由于很了解内部细节,所以可以避开许多“地雷”,但是,对大多数人来说,根本没有这种机会。那么,只有好好学习这种语言的基础与编程规范,借鉴别人的经验,多阅读、实践,这样才能有所帮助。

当然对于错误发生时该如何做的问题,我想可以这样解答,先找低级错误,看看自己的算法是否按照自己的预期进行了,然后如果还不能解决问题,才考虑一些相对高级的错误。大家不应该对自己那么没信心吧?一旦出错便立刻怀疑自己的算法逻辑错了,这样也未免太过自视过低了吧?

至于说到什么才是高级错误,我想以后有机会解答的。

2009.11.17凌晨一点:刚才在做课程设计,其实这段时间一直都在做,一步一步,按部就班,力争把Java练精,同时积累一下经验。上周末我把myeclipse下的项目整个拷回家继续做,回到来想都没想,就把原先那个项目文件夹删除了,然后把在家弄过的粘贴到原位。打开myeclipse后发现有点不对劲,没怎么理它。继续编译,可以啊!测试出错,提示内容有点怪:java.lang.UnsupportedClassVersionError: Bad version number in .class file at java.lang…………,有点郁闷,删掉几句重要的发现可以执行,补回一两句之后发现报的错很无厘头,不在经验范围内。想了想,关了myeclipse,然后把项目重新剪切了出来,打开myeclipse,删除里面的残余项目信息,重新导入项目,ok了。总结:不要擅作主张,自作聪明啊!有些东西估计还是要让它自己转化。现在想想,或许是家里用的myeclipse版本不大一致,又或者jdk版本不同,总之可能性很多……

还有一点,是关于递归的,如果递归有返回值,而根据算法逻辑,发生返回后就要一直返回至最初调用处的话,那么就应该在递归函数内的每个调用自身处的后面加上return语句,即所谓的return出来之后再return。关于这一点的重要性可以从某种不良习惯上得以体现。假定你觉得函数返回之后可以置之不理,认为它顺着执行下去会到达函数尾,而且自己在那里添加了return语句,认为到了那里自然就会return了,这种情况是存在的。但是,一旦你的函数还携带一些需要传递的参数时,在本应不断return出来再return的情况下不去这么做,那么你让程序顺着往下继续执行至尾,在这个过程可能已经不知不觉把某些关键量改掉了,这样就有麻烦了。所以,在不需要继续往下执行时,就应该让它返回,这样无论在算法逻辑上,还是在编程习惯上,都是非常合理的。

2009.11.24:最近一直在做那个课程设计,好累好累。学了不少知识,就当做是对旧知识的复习、巩固吧!在做的过程中也有意遵循面向对象编程的原则与规范去做。

刚才想到一些事情,做了一个小实验:

package testmethod;

/**
*
* @author Administrator
*/
public class Main {
    int v_instance = 0;
    static int v_static=1;
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
    }
    void method_instance(){
        
    }
   static void method_static(){
        
    } 
}
    

public class ClassForInstanceMethod {
   int a;
    static int b;
    /** Creates a new instance of ClassForInstanceMethod */
    public ClassForInstanceMethod() {
    }
    
   void method1(){
        
    }
    static void method2(){
        
    }
    
    void method(){
        a++;
        b++;
        a = b;
        b = a;
        
        Main m = new Main();
        
        m.method_instance();
        m.method_static();
        m.v_instance++;
        m.v_static++;
        
        Main.method_static();
    //   Main.method_instance();//wrong,non-static method can not be referenced from a static context
        Main.v_static++;
   //   Main.v_instance++;//wrong,non-static variable can not be referenced from a static context

        
        method1();
        method2();
    }
}


public class ClassForStaticMethod {
    int a;
    static int b;
    /** Creates a new instance of ClassForStaticMethod */
    public ClassForStaticMethod() {
    }
    
     void method1(){
        
    }
   static void method2(){
        
    }

    public static void method(){
      // a++;//wrong,non-static variable can not be referenced from a static context
        b++;
        b = b+1;
      // a = a+1;//wrong,non-static variable can not be referenced from a static context
        
        
        Main m = new Main();
        
        m.method_static();
        m.method_instance();
        m.v_instance++;
        m.v_static++;
      
        Main.method_static();
    //    Main.method_instance();//wrong,non-static method can not be referenced from a static context
        Main.v_static++;
    //    Main.v_instance++;//wrong,non-static variable can not be referenced from a static context
        
// method1();//wrong,non-static method can not be referenced from a static context
        method2();
    }
}
在静态方法中无法直接调用本类中的实例成员,而在实例方法中却可以。但是,不论在什么方法中,只要不是本类的成员,就无法直接调用,但可以通过类名、对象引用来调用。

今天,想做一个继承自JDialog的DialogClass,在构造方法中还调用了父类的构造器,super(parent,modal),其中parent为java.awt.Frame对象,modal为boolean类型变量。并在DialogClass中安放了四个按钮,装上监听器后发现怎么点击都没响应。很郁闷,不知道为什么会出问题,这可是照书上去做的。这样子想做个模态的自定义对话框就做不了了。由于时间紧迫,只好先搁置下来,等以后解决。

2009.11.26:

最近由于有做GUI的需要,所以先是尝试了在Myeclipse下安装swing包后做界面,不过发觉不好用,后来改用netbeans自带的窗体编写功能,发觉要容易用得多。

另外,顺便说一说怎么在netbeans的窗体中定制代码,很简单的,就是先窗体那儿点右键,选择“定制代码”,然后你会发现在弹出的对话框上面可以选择要定制代码的GUI对象,在需要给JButtonGroup添加按钮时,就应给它定制代码,其它情况与此类似。另外还要说一下的是,我在netbeans中选择创建java对话框窗体后发现,竟然可以是模态的,不知道当时在myeclipse中为何不行。

嗯,对了,最近老敲代码,搞到手指头好像有点不舒服……

2009.12.1:

连续几天没上来写日志了,都是为了做课程设计的,已经劳动了好久了。现在把最近的一些收获写出来。

先从JVM的堆大小heap space开始说起,最近做的文件处理系统,有文件检索的功能,我采用了ArrayList数据结构来记录搜索到的路径名,但最终由于数据量太大,导致heap space exception。我参阅了一下网上的资料,发现可以去调整JVM的堆大小,但是我在想C盘上的文件有几十万个,就算把堆大小调到最大,也未必能满足需要,更何况heap占用的内存太大的话,会严重影响其它线程的运行。所以,必须另寻它法。

最近经常与null pointer exception打交道,总结出了以下结论:1、属性初始化发生的位置需要深思熟虑,最好在声明处初始化,然后以后根据需要在其它的地方比如构造器、成员方法内重新赋值。2、有时候发生此异常是因为你没有把其值或者是对象引用传递进去。要调试它其实并不难,可以先定位到出错的地方,在一句一句用if语句判断输出提示。

用netbeans时发现,当你编写了多个类时,修改完后的必须编译一下,才能反映到运行时的效果中,有时候你编译漏了一个两个,而去执行主类,则想要的效果不会呈现出来。

最近用Java编程的一大体会时,想保存代码之前最好先备份,而且要多备份,因为项目比较大,一旦出错了就很难改回原本的样子了。所以不要嫌麻烦,要多备份。顺便说一下,因为做这个项目,是带有实用性的,也就是一开始做出来的并不是最终想要得到的功能,必须在已有的基础上提升功能,这就面临一个问题每次调试ok后没有多少bug了,但是以提升功能后立即引入新的bug,如果你不习惯经常调试,比如说每改动一处就编译运行一次,那么你的后期维护将会很困难,没有什么比在错误变得严重之前立刻把它消灭更明智的了。

要善于观察编译器左右两边靠近边线的地方的提示符,有时候它会告诉你:对自身赋值、隐藏了某个数据域、访问了静态方法之类的有用信息,要善于利用它们。

关于修饰符,也要说说:一个属性,它是静态的还是实例的,必须仔细考虑,因为这一步处理将牵扯到后续开发的软件结构,不得不认真思考。有以下可以关注的:实例的可以赋给静态的,常量应声明为public static final 的,而类内的大部分属性应声明为 private的,类属的应声明为static的,反之应声明为实例的,考虑到如何处理它们,应该为它们构造getter、setter,而getter、setter往往应该设计为public的(否则跨包无法看见),同理,类属的也应该声明为static的。

在编写GUI时,一大体会就是如果没必要,就不要使用dispose(),因为那样机器跑起来比较慢,特别是当你这样反复dispose(),然后重建时。最好使用setVisible(false),当然,这样就要求你不能随意要对象给丢弃了。或许你会考虑建造一个静态的类成员,这样相比实例成员的反复构造,显然要节省开销得多。

多写一些控制台的输出语句,就能够方便调试,发现异常时,应该首先定位到那里,并采用排除法来检测。

一个好的设计是能够减少对对象的反复创建的,而是考虑对象的复用。

使用局部变量的好处是用完方法即丢弃,而对于那些用完就不需要了的对象,显然应该这样处理。

有时候你会发现,原来return很有用。

当你看见关于stack、queue方面的异常交替出现的exception时,是否应该考虑一下你的类构造是否出现了嵌套构造,即父类中含有子类对象,奇怪的是编译器竟然不会报错?!这是个什么问题呢?即,构造父类对象时要创建子类对象作为成员,接着子类对象的构造又必须先为它创建父类对象,如此往复……出现异常。

在设计软件时,有时候,如果不需要对各种错误(用户误操作)进行针对性处理,可以考虑屏蔽掉它们,即,不予响应。

2009.12.4:不知不觉已经写了这么多了,最近一直比较忙,现在把一些心得写一下:

做一次大的项目,不管能考查你对编程技术、编程工具的掌握程度,而且可以考查你的软件工程思想——面向对象的软件工程思想。

对编程而言,调试很有必要。单元测试OK了,不代表万事大吉了,因为还要进行组合测试,这种时候需要关注些什么呢?提示:组合起来的模块往往是由几个小模块组成的,这些小模块之间需要通信,bug最容易出现在用于几个参与的模块之间的接口处,接口设计得好,往往是事半功倍的。

一开始的设计模式是很重要的,它适合问题与否、符合编程规范与否,直接决定了代码的易维护性、易扩展性、易修改性、易读性。你每做的一步设计策略,都要考虑其连带影响。要学会在问题的纵向上、横向上深思熟虑。

如果你要做一个项目,它的工作量比较大,那还不成问题。做快一点就行了,考验你的效率。

如果你要做一个项目,会遇到技术障碍,没关系,多看书,多学习就行了。

如果你要做一个项目,它很考验你的算法思想,没关系,多思考,练一下你的逻辑思维也不错,耐心思考。

如果你要做一个项目,需要做到上述所有,那么恭喜你,你杯具了!(*^__^*) ……

最近发觉原来调试也是一门艺术,如果你善于思考,就能够从程序所表露出来的种种问题中发现问题之所在,当然这要考查你的分析能力,有时候我甚至在我找到了问题的原因后想,刚才如果我那样分析的话,早就找到原因了。好的调试技巧,可以让你的效率提高,好的调试思想,可以让你有一个质的飞跃。

2009.12.11:最近在编程时发现,当在一个程序中,有几部分的数据域是互通的时候,也就说,部分数据要存储在几个不同的地方,而且由于某些原因,不能合并在一起使用的时候,数据的更新要特别小心,如果是出于某些特别需要而不采用同步更新,那么在后面的使用时就要留意数据域反映的是否是最新的数据,而且从一个比较合理的角度来思考,总有一个时候,你需要将这几部分的数据域修改至相同的状态,当然,这个时刻应该由你来小心把握。当数据域没有同步更新时,你或许会因为没有留意到这一点,而遭遇种种挫折。

2009.12.25:

最近做程序时,用到了图形界面,其中很重要的一环就是需要将组件定位到屏幕中心,或者是定位到某个父组件的中心。一开始我以为所有的坐标都是相对屏幕进行定位的,可是后来经检查发现显示出来的界面并非像我预期的那样。结果经仔细检查发现:对于画图方法,如drawString()、fillArc()等,都是相对其所在的组件的左上角为起点的。

另外一个是关于单位的问题:在Math.Sin()中单位是弧度,而在fillArc()中单位却是度,在javadoc里面也没有说得多清楚,但是在课本上倒是可以从代码上隐约看出单位变了。真郁闷啊!这一点大家无论如何都要注意了。

PS:从fillArc()中的参数startAngle可以看到angle:角度,即单位:度。度要转为弧度需要除以180,再乘上π。

还有一些收获是:

永远不要直接调用paintComponent()方法,系统会自己依情况调用。

用this可以区分方法域内的与域外的实例变量,若无域内的,而在方法内使用了this.val=val,则会变成自己赋值给自己,这一点编译器会有提示符提示。

在构造方法内调用其它构造方法,须用this(),而且必须用在首句。

如果在方法中使用了用const修饰的形式参数,比如const int val,那么编译器会将其与不用const修饰的int val区分开来,如果你在两个同名方法内分别使用了上面的两种形参,则会视为方法重载。

(不定时更新……)

0 0
原创粉丝点击