JAVA编程中应该注意的问题

原创 2004年10月22日 17:30:00

Exceiption

  • 使用try-catch-finally时,如果catch子句没有的话,异常有可能会丢失,这是一个非常严重的错误。所以,我们在使用try-catch-finally时,一定要增加一个catch(Exception ex)子句。另外一个策略就是将所有将抛出异常的方法都包装到try-catch中去,而且注意catch不要漏掉你不希望漏掉的异常。

  • 当们知道在我们的方法里面将会有可能抛出一个异常,我们是在这个方法里面就处理,还是处理一些留一些给上面的对象去处理,还是完全交给上面的对象去处理呢?我现在并没有好的标准来分析这个问题。

  • 可以用一个非常简单的方法对“检查型异常”进行包装,使之成为一个“非检查型异常”,而且要需要捕捉的时候能够使用getCause()方法捕捉并处理这个异常,下面是一个例子:

    class WrapCheckedException {
      void throwRuntimeException(int type) {
        try {
          switch(type) {
            case 0: throw new FileNotFoundException();
            case 1: throw new IOException();
            case 2: throw new RuntimeException("Where am I?");
            default: return;
          }
        } catch(Exception e) { // Adapt to unchecked:
          throw new RuntimeException(e);
        }
      }
    }


    class SomeOtherException extends Exception {}

    public class TurnOffChecking { private static Test monitor = new Test();
      public static void main(String[] args) {
        WrapCheckedException wce = new WrapCheckedException();
        // You can call f() without a try block, and let
        // RuntimeExceptions go out of the method:
        wce.throwRuntimeException(3);
        // Or you can choose to catch exceptions:
        for(int i = 0; i < 4; i++)
          try {
            if(i < 3)
              wce.throwRuntimeException(i);
            else
              throw new SomeOtherException();
          } catch(SomeOtherException e) {
              System.out.println("SomeOtherException: " + e);
          } catch(RuntimeException re) {
            try {
              throw re.getCause();
            } catch(FileNotFoundException e) {
              System.out.println(
                "FileNotFoundException: " + e);
            } catch(IOException e) {
              System.out.println("IOException: " + e);
            } catch(Throwable e) {
              System.out.println("Throwable: " + e);
            }
          }
        monitor.expect(new String[] {
          "FileNotFoundException: " +
          "java.io.FileNotFoundException",
          "IOException: java.io.IOException",
          "Throwable: java.lang.RuntimeException: Where am I?",
          "SomeOtherException: SomeOtherException"
        });
      }
    } ///:~


Finally

  • 不要乱用finally。我们很多时候不能确定在什么时候发生清理工作,或是我们不能确定finally会被调用。比如说我现在打开一个文件,然后有一个操作是从文件里面读取一段内容。这个读取的内容可以连续进行多次,直动用户不想用了为止。所以,我们根本不可能知道用户在什么会需要关闭文件这个操作,这个时候我们千万不要把文件关闭的动作放到finally中去执行。




Loop

  • 一个经常出的逻辑错误。

    Here is a common mistake people make when they are trying to do nested iteration over two collections:

    List suits = ...;
    List ranks = ...;
    List sortedDeck = new ArrayList();
    
    
    for (Iterator i = suits.iterator(); i.hasNext(); )
        for (Iterator j = ranks.iterator(); j.hasNext(); )
            sortedDeck.add(new Card(i.next(), j.next()));
    

    Can you spot the bug? Don't feel bad if you can't. Many expert programmers have made this mistake at one time or another. The problem is that the next method is being called too many times on the “outer” collection (suits). It is being called in the inner loop for both the outer and inner collections, which is wrong. In order to fix it, you have to add a variable in the scope of the outer loop to hold the suit:

    // Fixed, though a bit ugly
    for (Iterator i = suits.iterator(); i.hasNext(); ) {
        
        for (Iterator j = ranks.iterator(); j.hasNext(); )
            sortedDeck.add(new Card(suit, j.next()));
    }
    

    So what does all this have to do with the for-each construct? It is tailor-made for nested iteration! Feast your eyes:

    for (Suit suit : suits)
        for (Rank rank : ranks)
            sortedDeck.add(new Card(suit, rank));
    


Array

  • 一个一维数组调用clone()方法是深复制;多维数组调用clone()方法是浅复制。

  • 假定B类是A类的子类,v是一个A类型组组。v能保存B的实例。但是保存B的实例后,v[n]会是一个B类型的句柄,当v[n] = new A();操作时会发生一个运行期异常,但是v = new A[n];还是正确的操作。因为,v依然的类型还是A,只是v[n]的类型改变了。



Nesting interfaces

  • 实现接口的时候,不一定要实现嵌套在里面的接口。

  • 私有接口只有在定义它们的类里面实现。

  • 接口里面内嵌的接口不能是private的。




Unintended recursion

  • 在toString()方法里面用this,经常容易产生一个递归的无限循环。如:
      public String toString() {
        return " InfiniteRecursion address: " + this + "/n";
      }

  • 在任何方法内调用自己也会产生一个递归的无限循环。如:void fo() {this.fo();}




Inner Classes

  • 在内部类除了内部类的宿主类的子类外,其它类都不能直接创建内部类的实例。如果一个内部类被为private,那么即使是它的子类也不能够创建这个内部类的实例。例如:如果B是A的内部类,C继承A,D不继承A。那么我们在C中可以这样创建内部类B的实例:

    A.B b = new A.B()

    在D中不能这样做,在D中要创建内部类B的实例的话可能这样:

    A a = new A();
    A.B b = a.new B();

  • 除类外任意作用域里面的内部类(包括Local Inner Classes局部内部类和Anonymous Inner Classes匿名内部类)的访问范围只局限于它的作用域。如if() {class A {}},这个A类只有在if块内可以访问。使用局部内部类而不使用匿名内部类的唯一原因就是:你需要创建多个那种类的对象。

  • 在同一个地方不同的类里面可以用相同名字的内部类。如A和B里面都可以用内部类C,它们不会冲突。因为访问任何类部类都必须跟它的外部类名字连在一起,如:A.C。

  • 定义匿名内部类时,如果还要用到外面的对象,就必须把这个参数的reference声明为final。如:

    Object test(final String str) {
        return new Object() {
            private String value = str;
        };
    }

  • 要给匿名内部类进行初始化构造,有两个方法:一是实例话对象来初始化匿名内部类,如:new Object(i) {};。这儿对过i来对Object进行初始化,从而达到对这个匿名内部类初始化的效果。二是在匿名内部类的初始化部分来实现,不过这儿只有一个区域,不可能再实现对它的重构。也就是说,只有这一个构造函数。如:

    new Object(final String str) {
        private String value;
    {
        value = str;
        if(value.equals(“Test“))
            value = str + “OK!“;
    }
    //to do something...
    };
  • 内部类可以直接访问他的宿主类的成员。这一点非常的有用。如:

    public class Test {
        Object[] object = new Object[5];
        private class InnerTest {
            public void readObject(int i) {
                return object[i];
            }
        }
    }
  • 普通内部类中不能有static数据,static数据成员和嵌套类(nested classes)。

  • 继承内部类的时候,派生类必须在构造函数中给一个宿主类类型句柄,然后还要进行一点特殊的操作,如:
    class WithInner {
      class Inner {}
    }

    public class InheritInner extends WithInner.Inner {
      //! InheritInner() {} // Won't compile
      InheritInner(WithInner wi) {
        wi.super();
      }
      public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner ii = new InheritInner(wi);
      }
    } ///:~

  • 继承类的内部类跟父类的内部类同名,不会覆盖父类的内部类。他们是两个独立的实例,都有自己的命名空间。如A有一个内部类名字叫C,B是A的子类,B也声明一个内部类名字也叫C,A中的C是用A.C来表示的,而B中的C是用B.C来表示的,他们的名字不会有冲突。我们要求可以在B中通过C extends A.C,这样B.C就成为了A.C的一个子类,可以达到我们的一些特殊的要求。

  • nested classes

    1. 无所宿主类对象就能够创建嵌套类对象。

    2. 不能在嵌套类对象里面访问非static宿主类对象。

    3. 能访问static数据,static数据成员和嵌套类。

  • 为什么要使用内部类

    1. 每个内部类能够独立的继承某个“实现(implementation) ”,因此,内部类不会受“宿主类是否已经继承了别的实现”的约束。如:
      class A {}
      abstract class B {}
      class C extends A {
          B makeB() {
              return new B() {};
          }
      }

      public class MutiImplementation {
          public static void holdA(A a) {}
          public static void holdB(B b) {} 

          public static void main(String[] args) {
              C c = new C();
              holdA(c);
              holdB(c.makeB());
          }
      }

    2. 内部类能够有多个实例,而每个又都可以是它自己的,与宿主对象无关的状态信息。

    3. 一个宿主类能够放上好几个内部类,而每个内部类又都可以以各自不同的方式来实现同一个接口,或实现同一个类。

    4. 内部类对象创建的时间不受宿主类对象的创建的约束。

    5. 内部类不存在让人头晕的“is-a”关系。它是一个独立的实体。



      举例来说:Sequence.java要是没有内部类,我们用它实现一个selector接口,那么你只能说“sequence是一个selector”,于是每个Sequence里面就只能有一个selector。但是用内部类,你可以再定义一个方法getRSelector(),让它返回一个倒过来访问这个序列的selector。内部类提供了这种灵活性。

java编程的注意事项

1.在继承关系中子类方法的保护等级不能高于父类。 2.foreach 循环在用于输出时是没有角标和计数器的,而是直接抛出对应数组元素。 3.在循环中输入比较条件是要使用比较运算符=...
  • eclipse_yin
  • eclipse_yin
  • 2016年04月05日 20:08
  • 460

编码要注意的问题

不管你用什么语言进行开发,所有的优秀代码都会展示出共有的经典品质:简练,易于理解,模块化,层次性,设计良好,高效,优雅,并且清晰。简练。这意味着能用五行代码解决的问题,绝不用十行代码。这也意味着,必须...
  • cloudday
  • cloudday
  • 2008年07月03日 15:10
  • 424

Spring学习及整合遇到的问题(二)

问题一 org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate compon...
  • u012793120
  • u012793120
  • 2017年02月25日 12:28
  • 168

聚类分析应注意的问题

聚类分析应注意的问题   一般来讲,根据聚类分析方法将市场细分后,就可以将细分的结果与实际结合起来,进行目标市场选择和市场定位决策。然而,运用这种定量分析方法,因为实际情况的复杂性,仍需要我们注意这...
  • ysuncn
  • ysuncn
  • 2008年05月06日 14:23
  • 1893

链表操作时的一些注意事项

最近写8数码程序,中间用到了链表的操作。中间遇到了一些莫名奇怪的错误,导致调试了好长时间才弄出结果,具体有以下几点。 1、创建链表一定要有哨兵节点,这样有利于链表的插入操作(扫描时两个指针,curr...
  • nichilor
  • nichilor
  • 2011年03月21日 21:08
  • 425

多线程开发中需要注意的问题

多线程开发在 Linux 平台上已经有成熟的 Pthread 库支持。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4...
  • saizo123
  • saizo123
  • 2017年03月21日 23:04
  • 520

Ajax需要注意的几个问题

在应用Ajax时,需要注意安全问题、性能问题和浏览器兼容性问题,下面进行具体介绍。 一 安全问题 随着网络的普及,安全问题已经是一个不可忽略的重要问题了。由于Web本身就是不安全的,所以尽可能降低...
  • chengqiuming
  • chengqiuming
  • 2017年04月12日 10:49
  • 240

硬件电路设计方面的几个注意事项

CPU是这个系统的灵魂,所有的外围配置都与其相关联,这也突出了嵌入式设计的一个特点硬件可剪裁。 第一、电源确定   电源对于嵌入式系统中的作用可以看做是空气对人体的作用,甚至更重要:人呼吸的空气中...
  • xu_zhen_jun
  • xu_zhen_jun
  • 2015年05月28日 15:22
  • 1551

英译汉需要注意的几点

来自网站: http://www.360doc.com/content/14/0528/07/14153037_381611194.shtml动宾连接原则  在英译汉时,有许多翻译错误来源于动宾短...
  • lichen_yun
  • lichen_yun
  • 2017年03月15日 15:07
  • 334

malloc使用注意

Malloc和free对应,申请堆空间,和释放。 Malloc该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。 关于分配失败的原因,应该...
  • mgd916
  • mgd916
  • 2014年09月08日 22:23
  • 271
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JAVA编程中应该注意的问题
举报原因:
原因补充:

(最多只允许输入30个字)