Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Java 5.0 
:(
    Опции темы
AntonSaburov
Дата 11.11.2004, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Данная статья посвящена новой разработке компании SUN – JDK 5.0

Мы рассмотрим те особенности, которые разработчики посчитали ключевыми. Большинство (можно сказать даже, что практически вся) представленной информации читатель может найти на официальном сайте компании. Автор просто решил представить данные особенности на свой лад и снабдить некоторыми примерами.

ЗАМЕЧАНИЕ Если Вы еще не очень уверены в своем умении собирать программы и запускать их, ознакомьтесь с разделом FAQ.

Итак, какие особенности можно назвать революционными:

1. Generics – переводу в одно слово это понятие поддается с трудом. Можно дать приблизительно такую трактовку: «обобщенные характеристики всего класса».
В двух словах это выглядит так: раньше все, что программист помещал в классы Collection (Vector, List, Stack) имело тип Object. Если Вы получали элемент из Collection (например, типа String), то Вам необходимо было делать обязательно так:

Код

Vector v = …;

String str = (String)v.get(0);


Или если Вы хотели просмотреть всю коллекцию с помощью итератора, то раньше Вы делали так:

Код

Collection c =…;

for (Iterator i = c.iterator(); i.hasNext(); ) {
    System.out.println( ((String)i.next()).length());
}


Заметьте, что тут есть два момента. Во-первых, необходимо привести тип элемента из коллекции к нужному виду. И, во-вторых, надо быть уверенным, что он действительно String. НИКАКИХ гарантий, что там окажется именно String, Вам не давалось. В любой момент в коллекцию можно было положить любой другой тип данных. И соответственно дальше все было делом либо доверия – там нет ничего кроме String, либо надо было убеждаться, что тип именно String.
Теперь у Вас может быть такая уверенность – Вы можете на этапе компиляции указать, какой тип Вы хотите хранить в коллекции. И уже на этапе компиляции Вам скажут, что Вы делаете что-то не то.

Код

Collection<String> c = …;

for (Iterator<String> i = c.iterator(); i.hasNext(); )
    System.out.println(i.next().length());
}


Чтобы было нечто более конкретное, напишем полноценный пример.


Код

import java.util.*;

public class Test
{
    public static void main(String[] args)
    {
        Vector<String> v = new Vector<String>();
        v.add("12");
        v.add("123");
        v.add("1234");

        //v.add(new Integer(1));

        printCollection(v);
    }

    public static void printCollection(Collection<String> c)
    {
        for(Iterator<String> i= c.iterator(); i.hasNext(); ) {
            System.out.println(i.next().length());
        }
    }
}


При внимательном просмотре текста Вы увидите, что, кроме того, что объявлена переменная Vector, объявление снабжено указанием типа данных, которые могут быть использованы в данной коллекции. Но если Вы удалите комментарий в строке 12 (//v.add(new Integer(1));), то программа уже на этапе компиляции выдаст ошибки. И если Вам действительно важно, чтобы в Вашей коллекции не было ничего кроме String, Вы можете быть уверены, что так оно и будет – компилятор следит за этим.

Давайте попробуем собрать такой же пример, но уже без указания класса.
Код

import java.util.*;

public class Test1
{
    public static void main(String[] args)
    {
        Vector v = new Vector();
        v.add("12");
        v.add("123");
        v.add("1234");

        //v.add(new Integer(1));

        printCollection(v);
    }

    public static void printCollection(Collection c)
    {
        for(Iterator i= c.iterator(); i.hasNext(); ) {
            System.out.println( ((String)i.next()).length());
        }
    }
}


Программа соберется, но Вы можете увидеть предупреждения компилятора
Код

Note: Test1.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.


Давайте сделаем как просит компилятор и соберем еще раз с указанными ключом.
 javac -Xlint:unchecked Test.java

Мы увидим достаточно большое сообщение
Цитата

Test1.java:8: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.Vector
        v.add("12");
             ^
Test1.java:9: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.Vector
        v.add("123");
             ^
Test1.java:10: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.Vector
        v.add("1234");


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

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

2. The For-Each Loop – улучшенный вариант цикла прохождения по коллекции.
Возьмем наш первый пример, в котором мы распечатали длины всех строк из коллекции. Нам интересен цикл
Код

for(Iterator i= c.iterator(); i.hasNext(); ) {
    System.out.println( ((String)i.next()).length());
}


Теперь есть более упрощенный вариант такого цикла
Код

for(String s : c) {
        System.out.println(s.length());
}

В полном варианте наш пример будет выглядеть теперь вот так
Код

import java.util.*;

public class Test
{
    public static void main(String[] args)
    {
        Vector<String> v = new Vector<String>();
        v.add("12"); v.add("123"); v.add("1234");

        printCollection(v);
    }

    public static void printCollection(Collection<String> c)
    {
        for(String s : c) {
            System.out.println(s.length());
        } 

    }
}


Также можно поступить и с обычным массивом – распечатаем значения массива
Код

int[] a = …
for (int i : a)
    System.out.println(i);


3. Autoboxing/Unboxing – автоматическая упаковка в объект.
Давайте просто внимательно разберем пример

Код

import java.util.*;

public class Test
{
    public static void main(String[] args)
    {
        Vector<Integer> v = new Vector<Integer>();
        v.add(1);
        v.add(2);
        v.add(3);

        for(Integer i : v) {
            int assa = i;
            System.out.println(assa+100);
        }
    }
}


Заметьте, что в коллекцию можно вставлять объект типа Integer. И вообще в коллекцию можно было вставлять только наследников от Object. Т.е. раньше надо было писать
Код

v.add(new Integer(1));
v.add(new Integer(2));
v.add(new Integer(3));


А также получение числа из объекта Integer тоже надо было делать приведением типа к Integer и вызовом метода intValue(). В цикле это происходит автоматически. Вот в принципе и весь смысл этого нововведения. Но удобно очень smile

4. Enums – перечисления.
Раньше для объявления констант использовалась такая форма:
Код

public static final int SHAPE_BOX = 0;
public static final int SHAPE_OVAL = 1;
public static final int SHAPE_RECT = 2;

public static final int MALE = 0;
public static final int FEMALE = 1;


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

Код

public class Test
{
    public enum SHAPE { BOX, OVAL, RECT }
    public enum SEX { MALE, FEMALE }

    private SHAPE shape;
    private SEX sex;

    public Test(SHAPE sh, SEX sx)
    {
        shape = sh;
        sex = sx;
    }

    public String toString()
    {
        return shape.toString()+":"+sex.toString();
    }

    public static void main(String[] args)
    {
        Test t = new Test( SHAPE.BOX, SEX.FEMALE);

        System.out.println(t);
    }
}


Как видите теперь Вашему запутанному коду не удастся обмануть компилятор без Вашего соизволения smile

Казалось мелочь, но кроме того, что enum может хранить константы, они могут иметь методы!!!
Мне очень понравился пример из оригинального текста, который показывает пример планет.
Код

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass()   { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}
 


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

Код

public static void main(String[] args) {
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
 


Я специально ждал того момента, когда пытливый читатель обратит внимание на последнюю строку. Увидели?
Да, JAVA теперь имеет полноценный printf, который испокон веков был в языке Си/С++. Теперь он есть и в JAVA.

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

5. Переменное количество аргументов в методе
В принципе здесь особо много говорить не стоит – проще посмотреть на пример.

Код

public class Test
{
    public static void main(String[] args)
    {
        String par1 = new String("1");
        String par2 = new String("2");
        String par3 = new String("3");
        showParam(par1, par2, par3);
    }

    public static void showParam(Object... args)
    {
        for(Object o : args) {
            System.out.println(o.toString());
        }
    }
}



6. Импорт статических переменных/констант
По большому счету это просто более удобный метод использования констант. Частенько бывает, что только ради какой-то константы приходится делать import ко всему классу. А бывает, что лениво перечислить классы и import вытаскивает полный пакет. Выглядит это не очень красиво. И потому теперь вы можете импортировать статическую и больше ничего. Насколько это удобно – даже не знаю что сказать.

Выглядит это так:
Код

package ansa.constants;

public class GlobalConstant
{
    public static final double PI = 3.14159; 
    ….
}

И теперь в другом пакете Выможете написать таким образом:
Код

import static ansa.constants.GlobalConstant.PI;

Вы можете использовать также все константы, которые описаны в Вашем классе. Вот как это выглядит:
Код

import static ansa.constants.GlobalConstant.*;


7. Аннотация (метаданные)
Идея аннотации (мета-данных) предложена для того, чтобы в процессе работы программы Вы бы могли получить информацию не только о методах, классах и параметрах, но и какие-то дополнительные значения или параметры, которые могут дать дополнительную характеристику. Объем стаьи не позволяет растекаться «по древу», поэтому приведу просто пример, к которому будут даны объяснения.

Код

import java.lang.annotation.*;
import java.lang.reflect.*;                                                                                

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 
@interface debug  
{    
    String comment();


@debug(comment="Comment for MetaTest class") 
public class MetaTest 
{    
    @debug(comment="Comment for member production") 
    public boolean production=true;

    @debug(comment="Comment for testMethod") public void testMethod()  {    }

    public static void main(String[] args) 
    {
        MetaTest mt = new MetaTest();
        try {
            Annotation[] ant1 = mt.getClass().getAnnotations();
            for (Annotation a : ant1) {
                System.out.println(a);
            }

            System.out.println("-----------------------");
            Annotation[] ant2 = mt.getClass().getMethod("testMethod").getAnnotations();
            for (Annotation a : ant2) {
                System.out.println(a);
            }

            System.out.println("-----------------------");
            Annotation[] ant3 = mt.getClass().getField("production").getAnnotations();
            for (Annotation a : ant3) {
                System.out.println(a);
            }
        }
        catch(NoSuchMethodException e) {
            System.out.println(e);
        }
        catch(NoSuchFieldException e) {
            System.out.println(e);
        }
    }
}


Давайте потихонечку разберемся с нашей программой. Первая непонятка это строка, которая начинается с @Retention(...
Разработчики JDK 5.0 предложили следующий способ введения мета-данных:
Программист описывает структуру тех мета-данных, которые он будет использовать. Я ввел структуру, которая содержит всего одно поел – comment
Полная запись мета-данных выглядит так:
Код

@interface debug  
{    
    String comment();


После введения мета-данных программист может использовать эти мета-данные где ему интересно. Понятно, что таких структур будет не одна, а много. Мы для примера взяли одну. Везде, где встречается @debug (кроме описания) мы видим, что в скобках указана пара «параметр=значение».
Очень важно отметить, что перед описанием структуры @debug стоит структура @Retention. Именно отсутствие этой записи заставило мучаться несколько часов автора статьи – все собиралось, но аннотация исчезала во время запуска. Этот параметр указывает, как следует обходиться с теми мета-данными, которые описаны после нее. Мы использовали параметр  java.lang.annotation.RetentionPolicy.RUNTIME. Это значение говорит о том, что информация из мета-данных будет сохранена даже при запуске приложения. Другие значения (CLASS, SOURCE) говорят, что эта информация не будет доступна во время выполнения (смотрите JavaAPI for JDK 5.0).
А дальше все очень просто – мы использовали данную структурудля хранения информации для самого класса, параметра и метода.
В методе main мы по очереди попросили венуть аннотации у самого класса, потом у метода и поля. Если Вы немного поиграете с данной программой, то поймете достаточно много.

Вот в принципе и все наиболее важные новинки, которые ждут Вас в JDK 5.0. На взгляд автора их достаточно много

Все замечания и пожелания автор принимает с удовольствием.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0613 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.