1.比较对象==

新手程序员最喜欢犯的错误是使用==运算符比较对象(尤其是字符串)。例如:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1 == s2)
{
   System.out.println("The strings are equal");
}

此代码永远不会显示“字符串相等”,因为该if语句比较对两个不同字符串对象的引用。

这是代码的正确版本:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1.equals(s2))
{
   System.out.println("The strings are equal");
}


2.改变String对象

新手程序员经常忘记类的所有对象都是不可变的,并且String类的每个方法都返回一个新对象——当前对象永远不会改变。

例子:

String s = "Hello";
s.toUpperCase (); // Convert to uppercase

此代码与正确的代码非常相似,但它不会按预期工作。该toUpperCase()方法不会更改调用它的对象。正确的代码如下所示:

String s = "Hello";
String result = s.toUpperCase(); // Convert to uppercase


3. 忘记初始化作为数组元素的对象

另一个常见的错误是忘记初始化数组变量。例子:

int[] array;
array[0] = 1;
array[0] = 2;

此代码不起作用:您需要显式地将数组变量设置为对将存储数组元素的容器对象的引用。

int[] array = new int[10];
array[0] = 1;
array[0] = 2;


4. 使用局部变量而不是实例变量。

新手不喜欢为变量起一个又长又有意义的名字。他们经常使用单字母名称:a, b,i等。当代码有多个这样的变量时,这是一件残酷的事情:

将数字 99 放入数组的 100 个单元格中
class Solution
{
  public static int a = 99;
  public static int i = 100;

  public static void main(String[] args)
  {
    int[] a = new int[i];
    for (int i = 0; i < 10; i++)
    {
      a[i] = a;
    }
  }
}

上面的代码不会编译。正确的版本如下所示:

将数字 99 放入数组的 100 个单元格中
class Solution
{
   public static int value = 99;
   public static int count = 100;

   public static void main(String[] args)
   {
      int[] a = new int[count];
      for (int i = 0; i < count; i++)
      {
         a[i] = value;
      }
   }
}


5.删除收藏品

经常会出现需要从集合中删除某个元素的情况。代码大致如下所示:

ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

for (Integer value: list)
   if (value < 0)
      list.remove(value);

此代码将不起作用,因为您不能使用 for-each 循环同时遍历集合的元素并修改该集合。

有几种解决方案。首先,您可以遍历一个集合并更改另一个集合:

解决方案 1
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

ArrayList<Integer> copy = new ArrayList<Integer>(list);
for (Integer value: copy)
   if (value < 0)
      list.remove(value);

其次,从 Java 8 开始,集合有一个removeIf()方法,您可以向该方法传递一个规则(lambda 函数)来指示要删除的元素。

例子:

方案二
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

list.removeIf( x-> x<0 );


6. 将带有修饰符的几个类public放入一个文件中

一个文件中只能有一个公共类。可以在文件中声明更多的类,但它们必须是公共类的内部类,或者没有修饰符public。例子:

Solution.java 文件的内容 笔记
public class Solution
{
}
public class Main
{
}
这是不允许的:一个文件中有两个公共类。
public class Solution
{
}
class Main
{
}
但你可以做到这一点。主类不公开
public class Solution
{
  public static class Main
  {
  }
}
你可以做到这一点。主类是一个嵌套类


main()7. 从静态方法调用类的普通(非静态)方法

有时,新手程序员会尝试从方法或其他静态方法访问非静态变量和方法main()。当然,这样的代码是行不通的。

public class Solution
{
   public int n = 100;
   public int[] createArray()
   {
      return new int[n];
   }

   public static void main(String[]args)
   {
      int[] array = createArray();
   }
}

main 方法只能引用静态方法/变量。好吧,否则它必须首先创建类的实例Solution,然后才调用该对象的非静态方法。例子:

解决方案 1 方案二
public class Solution
{
  public static int n = 100;

  public static int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    int[] array = createArray();
  }
}
public class Solution
{
  public int n = 100;

  public int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    Solution sol = new Solution();
    int[] array = sol.createArray();
  }
}


8. 像方法一样声明构造函数

另一个常见错误是错误地声明了类构造函数。构造函数的名称必须与类的名称相同,并且构造函数没有结果类型。最常见的错误如下所示:

public class Person
{
   private String value;

   void Person(String value)
   {
      this.value = value;
   }
}




这里不应该有返回类型
public class Person
{
   private String value;

   constructor(String value)
   {
      this.value = value;
   }
}




无效的构造函数名称。构造函数的名称必须与类名匹配
public class Person
{
   private String value;

   Person(String value)
   {
      value = value;
   }
}






this 不见了。该value变量将被分配给自己
public class Person
{
   private String value;

   Person(String value)
   {
      this.value = value;
   }
}




都是对的


9.接口继承不正确

Java的创造者试图使它非常接近英语,因此他们为某些相关概念选择了不同的关键字。

当一个类继承一个类时,你必须使用关键字extends

class Pet
{
}

class Cat extends Pet
{
}

当类继承接口时,需要使用关键字implements

interface Meow
{
}

class Cat implements Meow
{
}

当一个接口继承一个接口时,使用extends关键字:

interface Meow
{
}

interface Voice extends Meow
{
}


10.遗漏break声明switch

break今天我们犯的最后一个错误,但不是初学者的最后一个错误,是没有在声明中包含声明switch。例子

错误的 正确的
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
   case TUESDAY:
      System.out.println("Tuesday");
   case WEDNESDAY:
      System.out.println("Wednesday");
   case THURSDAY:
      System.out.println("Thursday");
   case FRIDAY:
      System.out.println("Friday");
   case SATURDAY:
      System.out.println("Saturday");
   case SUNDAY:
      System.out.println("Sunday");
}
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
      break;
   case TUESDAY:
      System.out.println("Tuesday");
      break;
   case WEDNESDAY:
      System.out.println("Wednesday");
      break;
   case THURSDAY:
      System.out.println("Thursday");
      break;
   case FRIDAY:
      System.out.println("Friday");
      break;
   case SATURDAY:
      System.out.println("Saturday");
      break;
   case SUNDAY:
      System.out.println("Sunday");
      break;
}