2008-11-03 2 views
65

Java близится к версии 7. Мне приходит в голову, что должно быть много учебников и учебных пособий, которые начинают использовать методы обучения, основанные на более старых версиях Java, где преподаются методы , теперь будут иметь гораздо лучшие решения.Java: Out with the Old, In with the New

Каковы некоторые ситуации с шаблоном кода, особенно те, которые вы видите, что люди реализуют с помощью привычки, что вы оказываете рефакторинг для использования последних версий Java?

ответ

70

Enums. Замена

public static final int CLUBS = 0; 
public static final int DIAMONDS = 1; 
public static final int HEARTS = 2; 
public static final int SPADES = 3; 

с

public enum Suit { 
    CLUBS, 
    DIAMONDS, 
    HEARTS, 
    SPADES 
} 
45

Generics и больше не нужно создавать итератор, чтобы пройти через все элементы в коллекции. Новая версия намного лучше, проще в использовании и понятна.

EDIT:

До:

List l = someList; 
Iterator i = l.getIterator(); 
while (i.hasNext()) { 
    MyObject o = (MyObject)i.next(); 
} 

После

List<MyObject> l = someList; 
for (MyObject o : l) { 
    //do something 
} 
+0

В основе механизма нового цикла for по-прежнему создается итератор, вам просто не нужно выписывать для него шаблонный код. – 2008-11-03 16:18:13

+0

Я как раз собирался сказать, что, sk – i3ensays 2008-11-03 16:26:43

+10

да, но дело в том, что в вашем коде вам НЕ нужно писать его, и это хорошая функция для новых версий Java. Просто потому, что на заднем плане ничего не изменилось, это не значит, что это не очень хорошая функция. – Elie 2008-11-03 16:59:04

12

Q1: Ну, наиболее очевидные ситуации в конкретных коллекций дженерики/типа. Другой, который сразу же приходит на ум, - это улучшенный цикл, который, как я чувствую, выглядит более чистым и понятным.

Q2: В общем, я связывал JVM вместе с моим приложением для приложений, ориентированных на клиента. Это позволяет нам использовать новые языковые функции, не беспокоясь о несовместимости JVM.

Если бы я не связывал JRE, я бы, вероятно, придерживался 1.4 по соображениям совместимости.

+0

старайтесь публиковать один ответ за раз (так что каждый может оцениваться отдельно) – i3ensays 2008-11-03 16:21:41

+0

Я не уверен, что вы имеете в виду ...? – 2008-11-03 16:37:44

10

Преобразование числа в строку:

String s = n + ""; 

В этом случае я думаю, что всегда был лучший способ сделать это:

String s = String.valueOf(n); 
+0

String.valueOf (n) выполняет эту последнюю задачу. – 2008-11-03 15:30:25

+1

Строка s = n + ""; это плохая привычка, потому что она всегда создаст новый объект. valueOf умнее об этом. – cynicalman 2008-11-03 15:32:11

+0

Вы правы, слишком рано утром я совсем забыл о String.valueOf (n). Я обновил его. – Kip 2008-11-03 15:41:28

12

Простое изменение, так как 1,5, но делает небольшое различие - в Swing API доступ к ContentPane из JFrame:

myframe.getContentPane().add(mycomponent); 

становится

myframe.add(mycomponent); 

И, конечно же, введение Enums изменило способ использования многих приложений, которые использовали константы в прошлом.

String.format() значительно улучшил манипуляции с строками, а утверждение trernary if весьма полезно для упрощения чтения кода.

+0

Если я правильно помню, myframe .add (...), используемый для вывода предупреждающего сообщения на stderr. – 2008-11-03 16:35:39

24

Вот еще один, что я вижу:

String.split()StringTokenizer против.

StringTokenizer не рекомендуется для нового кода, но я по-прежнему вижу, что люди его используют.

Что касается совместимости, Sun прилагает огромные усилия, чтобы Java была совместима в обратном и обратном направлении. Это частично объясняет, почему дженерики настолько сложны. Предполагается также, что устаревание облегчит переход от старого к новому.

+1

:(Не слышал, что StringTokenizer больше не рекомендуется. Мне нравится StringTokenizer! Отлично подходит для декодирования коммутируемых входов и сложных операторов. Вещи, где, похоже, было бы очень сложно сделать с split(). – 2008-11-03 17:26:02

37

Использование локальных переменных типа StringBuffer для выполнения конкатенации строк. Если синхронизация не требуется, вместо этого теперь рекомендуется использовать StringBuilder, потому что этот класс обеспечивает лучшую производительность (предположительно потому, что он несинхронизирован).

+2

ArrayList является предпочтительным для Vector и HashMap для Hashtable по той же причине. – Kip 2008-11-03 19:03:36

+3

Некоторые современные JIT могут сказать, когда блокировка является локальной и оптимизирована, что делает StringBuffer так же быстро, как StringBuilder ... но я не совсем помню, какие именно JVM (ы), которые это сделали. – 2008-11-03 19:48:06

17

Использование локальных переменных типа Vector для хранения списка объектов. Если синхронизация не требуется, теперь рекомендуется использовать реализацию List, такую ​​как ArrayList, потому что этот класс обеспечивает лучшую производительность (поскольку он несинхронизирован).

+0

Это что-то новое? Я думал, что это всегда так. – Liam 2008-11-03 17:42:49

+1

Зависит от того, как вы определяете «новое». Я застрял в написании кода Java 1.1 (поэтому мы можем поддерживать людей, которые отказываются обновляться от MS JVM), и тогда несинхронизированные коллекции не существовали. – Herms 2008-11-03 18:05:23

+0

Это не совсем правильно. Вектор - это совершенно другой тип данных из ArrayList - т. Е. посмотрите на метод setSize. Тем не менее, в большинстве случаев векторный тип не требуется. – 2008-11-03 19:20:58

15

Явное преобразование типов примитивов и оболочек (например, Integer в int или наоборот), которые автоматически обрабатываются автобоксированием/распаковкой с Java 1.5.

Примером может служить

Integer myInteger = 6; 
int myInt = myInteger.intValue(); 

Может просто быть записана в виде

Integer myInteger = 6; 
int myInt = myInteger; 

Но следить за NullPointerExceptions :)

2

Новая версия Java редко сломать существующий код, так что просто оставить старый кода и сосредоточиться на том, как новая функция облегчает вашу жизнь.

Если вы просто оставите старый код один, то писать новый код с помощью новых функций не так страшно.

+1

Это нормально, если ваш старый код абсолютно без ошибок, никогда не нуждается в обслуживании! – Liam 2008-11-03 17:45:09

11

Универсальные коллекции делают кодирование более устойчивым к ошибкам. OLD:

Vector stringVector = new Vector(); 
stringVector.add("hi"); 
stringVector.add(528); // oops! 
stringVector.add(new Whatzit()); // Oh my, could spell trouble later on! 

NEW:

ArrayList<String> stringList = new ArrayList<String>(); 
stringList.add("hello again"); 
stringList.add(new Whatzit()); // Won't compile! 
24

Пожилой кода с использованием темы вместо многих других альтернатив Thread ... в эти дни, очень мало коды я бег по-прежнему необходимо использовать сырой поток. Их лучше обслуживать уровень абстракции, в частности Callable/Futures/Executors.

См:

java.util.Timer

javax.swing.Timer

java.util.concurrent.*

11

Использование итератора:

List list = getTheList(); 
Iterator iter = list.iterator() 
while (iter.hasNext()) { 
    String s = (String) iter.next(); 
    // .. do something 
} 

Или альтернативная форма иногда видели:

List list = getTheList(); 
for (Iterator iter = list.iterator(); iter.hasNext();) { 
    String s = (String) iter.next(); 
    // .. do something 
} 

теперь все заменены:

List<String> list = getTheList(); 
for (String s : list) { 
    // .. do something 
} 
1

сравнения строк, действительно старая школа Java программистов я встретил бы:

String s1 = "...", s2 = "..."; 

if (s1.intern() == s2.intern()) { 
    .... 
} 

(Якобы для выполнения причины)

Принимая во внимание, что в эти дни большинство людей просто делают:

String s1 = "...", s2 = "..."; 

if (s1.equals(s2)) { 
    .... 
} 
21

VARARGS также может быть полезен.

Например, вы можете использовать:

public int add(int... numbers){ 
    int sum = 0 ; 
    for (int i : numbers){ 
     sum+=i; 
    } 
    return sum ; 
} 

вместо:

public int add(int n1, int n2, int n3, int n4) ; 

или

public int add(List<Integer> numbers) ; 
1

Использование Vector вместо новых коллекций.

Использование классов вместо перечислений

public class Enum 
    { 
     public static final Enum FOO = new Enum(); 
     public static final Enum BAR = new Enum(); 
    } 

Использование тему вместо нового пакета java.util.concurrency.

Using marker interfaces instead of annotations

5

Изменение JUnit тестов 3-стиль:

class Test extends TestCase { 
    public void testYadaYada() { ... } 
} 

для JUnit тестов 4 стиля:

class Test { 
    @Test public void yadaYada() { ... } 
} 
11

Хотя я признаю, что статический импорт может быть легко злоупотреблять, мне нравится для использования

import static Math.* ; 

в классах, которые используют множество математических функций. Это может действительно уменьшить многословие вашего кода. Однако я бы не рекомендовал его для менее известных библиотек, поскольку это может привести к путанице.

8

Новый for -Каждая конструкция для перебора массивов и коллекции является самой большой для меня.

В эти дни, когда я когда-либо увидеть шаблонный for цикл для перебора массива один за другим с помощью индексной переменной, это заставляет меня хотеть кричать:

// AGGHHH!!! 
int[] array = new int[] {0, 1, 2, 3, 4}; 
for (int i = 0; i < array.length; i++) 
{ 
    // Do something... 
} 

Замена выше с for construct introduced in Java 5 :

// Nice and clean.  
int[] array = new int[] {0, 1, 2, 3, 4}; 
for (int n : array) 
{ 
    // Do something... 
} 

Чистый, краткий, и лучше всего, это дает смысл к коду, а не показывая как сделать что-нибудь г.

Очевидно, что код имеет смысл перебирать по коллекции, а не старый цикл for, говорящий о том, как перебирать массив.

Кроме того, поскольку каждый элемент обрабатывается независимо от других элементов, он может обеспечить будущую оптимизацию для параллельной обработки без необходимости внесения изменений в код. (Просто спекуляция, конечно.)

16

Форматированная печать была введена уже в JDK 1.5. Таким образом, вместо того, чтобы использовать:

String str = "test " + intValue + " test " + doubleValue; 

или эквивалент с помощью StringBuilder,

можно использовать

String str = String.format("test %d test %lg", intValue, doubleValue); 

Последнее является гораздо более удобным для чтения, как из конкатенации и версий строк строитель , Тем не менее я считаю, что люди принимают этот стиль очень медленно. Например, система Log4j не использует это, хотя я считаю, что это было бы очень полезно для этого.

3

Преобразование классов в использование дженериков, что позволяет избежать ситуаций с ненужными приведениями.

3

Я немного настороженно рефакторирую вдоль этих строк, если это все, что вы делаете с вашим исходным деревом. Примеры до сих пор не кажутся одними причинами для изменения любой рабочей базы кода, но, возможно, если вы добавляете новую функциональность, вы должны использовать все новые вещи.

В конце концов, это пример не очень удаление котла кода пластины, они просто используя более управляемые конструкции новых JDKs для сделать хорошо выглядящий котла кода пластины.

Большинство способов сделать ваш код элегантным не в JDK.

3

Хорошо, теперь настала моя очередь кричать.

Я не рекомендую 90% этих изменений.

Это не значит, что использовать их с новым кодом не рекомендуется, но взломать существующий код, чтобы изменить цикл for на цикл for (:) - это просто пустая трата времени и шанс что-то сломать. (IIWDFWI) Если это работает, не исправляйте это!

Если вы находитесь в реальной компании-разработчике, это изменение теперь становится чем-то вроде проверки кода, проверки и, возможно, отладки.

Если кто-то, кто делает такой рефакторинг без причины, вызвал проблему ЛЮБОГО рода, я бы не дал им окончательного дерьма.

С другой стороны, если вы все равно находитесь в коде и меняете материал на этой линии, не стесняйтесь его очищать.

Кроме того, все предложения во имя «Производительность» действительно должны узнать о законах оптимизации. В двух словах: «Не делай! Когда-либо! (Google «Правила оптимизации, если вы не верите мне)

7

, относящиеся к varargs;. Метода полезности Arrays.asList() который, начиная с Java 5, принимает параметры переменной длины является чрезвычайно полезным

Я часто ловлю себя. упрощая что-то вроде

List<String> items = new ArrayList<String>(); 
items.add("one"); 
items.add("two"); 
items.add("three"); 
handleItems(items); 

с помощью

handleItems(Arrays.asList("one", "two", "three")); 
34

читает строку из стандартного ввода:

Java до 5:

try { 
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 
    String str = reader.readLine(); 
    reader.close(); 
} 
catch (IOException e) { 
    System.err.println("error when closing input stream."); 
} 

Java 5:

Scanner reader = new Scanner(System.in); 
String str = reader.nextLine(); 
reader.close(); 

Java 6:

Console reader = System.console(); 
String str = reader.readLine(); 
3

Использование Свинг новый DefaultRowSorter для сортировки таблиц по сравнению с прокруткой с нуля.

0

Стоит отметить, что Java 5.0 существует уже пять лет, и с тех пор произошли незначительные изменения. Вам придется работать над очень старым кодом, чтобы все еще рефакторировать его.

10

копирования существующего массива в новый массив:

предварительной Java 5:

int[] src = new int[] {1, 2, 3, 4, 5}; 
int[] dest = new int[src.length]; 
System.arraycopy(src, 0, dest, 0, src.length); 

Java 6:

int[] src = new int[] {1, 2, 3, 4, 5}; 
int[] dest = Arrays.copyOf(src, src.length); 

ранее, я должен был явно создать новый массив, а затем скопируйте исходные элементы в новый массив (вызывая метод с большим количеством параметров). теперь синтаксис чист, и новый массив возвращается из метода, мне не нужно его создавать. Кстати, метод Arrays.copyOf имеет вариацию под названием Arrays.copyOfRange, которая копирует конкретную область исходного массива (примерно как System.arraycopy).

6

Аннотации

Интересно, что никто не упомянул об этом до сих пор, но многие структуры опираются на аннотации, например Spring и Hibernate. Обычно сегодня принизить конфигурационные файлы XML в пользу аннотации в коде (хотя это средство теряя гибкость при переходе от конфигурации к метакоду, но часто это правильный выбор). Лучшим примером является EJB 2 (и старше) по сравнению с EJB 3.0 и как упрощение программирования EJB благодаря аннотациям.

Я считаю, что аннотации также очень полезны в сочетании с некоторыми инструментами AOP, такими как AspectJ или Spring AOP. Такая комбинация может быть очень сильной.

4

Улучшенные одноэлементные узоры. Технически они охвачены популярным списком ответов, но это значимая подкатегория.

public enum Singleton { 
    INSTANCE; 

    public void someMethod() { 
     ... 
    } 
} 

чище и безопаснее, чем

public class Singleton { 
    public static final Singleton INSTANCE = new Singleton(); 

    private Singleton() { 
     ... 
    } 

    public void someMethod() { 
     ... 
    } 
}