четверг, июля 29, 2010

Простейшее приложение с использованием Silverlight / RIA / POCO

В данном посте своего хай-тек блога я-бы хотел показать вам как создать простейшее приложение на Silverlight с использованием RIA/POCO. Этот пример будет настолько прост на сколько это возможно. Для этого будем рассматривать только вариант с чтением данных. Про обновление поговорим в следующий раз.
Итак нам понадобится

  1. Скачать и установить Silverlight 4.0 и WCF RIA Services 1.0
  2. Скачать Silverligth Toolkit
  3. Создать компонент бизнес слоя
Когда вы приступаете к созданию приложения Silverlight/RIA у вас уже обычно есть слой бизнес компонент которые вы будете использовать. В этом примере вы будем использовать простейший класс Customer.
Создайте проект стандартной библиотеки классов (Class Library) и добавьте туда следующий код:














using System.Collections.Generic;
namespace ACM.BLCSharp
{
    ///
    /// Manages a customer
    ///

    public class Customer
    {
        public int CustomerId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string EmailAddress { get; set; }
        ///
        /// Retrieves a list of customers.
        ///

        ///
        ///
        /// In a "real" application, this code would
        /// call a data access component that retrieves
        /// the data from a database.
        ///

        public List Retrieve()
        {
            List custList = new List
                    {new Customer()
                          { CustomerId = 1,
                            FirstName="Bilbo",
                            LastName = "Baggins",
                            EmailAddress = "bb@hob.me"},
                    new Customer()
                          { CustomerId = 2,
                            FirstName="Frodo",
                            LastName = "Baggins",
                            EmailAddress = "fb@hob.me"},
                    new Customer()
                          { CustomerId = 3,
                            FirstName="Samwise",
                            LastName = "Gamgee",
                            EmailAddress = "sg@hob.me"},
                    new Customer()
                          { CustomerId = 4,
                            FirstName="Rosie",
                            LastName = "Cotton",
                            EmailAddress = "rc@hob.me"}};
            return custList;
        }
    }
}
Обычно я создаю пару классов: Customer - для представления единичной записи и Customers для операций над списками. Для упрощения в этом примере этим занимается один класс. Как вы заметили данный класс для упрощения не использует слой доступа к данным.


Шаг первый: добавить атрибуты на объекты предназначенные для Silverlight
Существуют несколько атрибутов которыми вы можете снабдить свой бизнес объект для улучшения их совместной работы с Silverlight. Но о единственным необходимым атрибутом для работы с WCF RIA является атрибут Key который, будучи примененным к свойству объекта, задает это свойство как уникальный ключ объекта. В нашем примере это свойство CustomerId.

using System.ComponentModel.DataAnnotations;
[Key()]
public int CustomerId { get; set; }

Шаг второй: создание проекта Silverlight

  1. Щелкните правой кнопкой на решении и выберите Add > New Project
  2. Выберите Silverlight > Silverlight Application (Будте внимательны и добавляйте проект для своего языка)
  3. Поставить галочку Enable WCF RIA Services


Когда вы добавляете проект Silverligth то Visual Studio создаст и проект Silverligth и проект ASP.NET. Второй важен из-за двух аспектов:

  • Он содержит код для запуска Silverligth приложения
  • Он предоставляет сервис WCF для общения между вашим Silverligth приложением и вашими бизнес объектами.
Если же у вас уже есть созданный проект Silverlight вы все еще можете включить WCF RIA в настройках проекта:




Шаг третий: добавьте ссылку на Бизнес Компоненты в проект ASP.NET приложения
Выберите свое ASP.NET приложение затем Add Reference и там свое проект с бизнес объектами. Таким образом мы разрешаем ASP.NET проекту доступ к нашему бизнес слою.

Шаг четвертый:Добавить Domain Service Class
Добавьте Domain Service Class а в приложение ASP.NET (он вызывает методы вашего бизнес слоя). Данный класс должен быть размещен а ASP.NET приложении, а не в приложении Silverlight т.к. последнее исполняется в браузере клиента а ASP.NET приложение выполняется на сервере где может получить доступ в вашим бизнес компонентам.
Чтобы добавить Domain Class Service щелкните правой кнопкой мышки на ASP.NET приложении и выберите Add > New Item, и там выберите шаблон Domain Service Class.
В этом месте у нас сильное различие с примером от Entity Framework. Если-бы мы использовали данный фреймворк то тут был-бы список сущностей. Если-же ,как в нашем случае, использовать  свои бизнес объекты, то тут будет пусто. Все нормально. Просто нажмите ОК.
Так-как мы используем свои бизнес объекты - Visual Studio будет наслежовать наш класс от DomainService. Если-бы мы использовали Entity Framework класс наследовался-бы от LinqToEntitiesDomainService.
В большинстве случаев вы будете создавать Domain Service Class для каждого из своих бизнес объектов.


Шаг пятый: Добавить метод запроса данных к Domain Service Class
Метод запроса должен вызывать метод Retrive бизнес-объекта.

namespace ACM.SilverlightCSharp.Web
{
    using System.Collections.Generic;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using ACM.BLCSharp;
    [EnableClientAccess()]
    public class CustomerDomainService : DomainService
    {
        public IEnumerable GetCustomers()
        {
            Customer cust = new Customer();
            return cust.Retrieve();
        }

    }
}


Несколько замечаний по поводу метода GetCustomers

  • Должен быть методом а не свойством
  • Должен возвращать одно из следующих:





    • Единичную сущность
    • IEnumerable где T - единичная сущность
    • IQueryable где T - единичная сущность
  • Может иметь любые параметры
  • Может иметь любое имя
  • Может (но не обязан) содержать атрибут Query что-бы задать метода как запрос
WCF RIA Services распознает метод как запрос благодаря типу возвращаемого значения. Таким образом метод должен иметь один из трех типов о которых говорилось ранее.
Если вы построите проект в данный момент и посмотрите все файлы то в папке Generated_Code  Silverlight проекта вы увидите .g.csc файлы. Это сгенерированный код для:
  • Классы сущностей (Customers в нашем примере) - генерируется из объектов бизнес-слоя и включает в себя все свойства сущности.
  • Класс Domain Context  (CustomersDomainContext в нашем примере) - через инфраструктуру WCF вызывает методы Domain Service Class нашего ASP.NET проекта
В добавок ко всему сгенерированный код содержит контракт сервиса для Domain Service Class в ASP.NET приложении

Шаг шестой: Создание UI
И опять для упрощения примера будем использовать грид для отображения данных.
  1. Откройте дизайнер файла MainPage.xaml (двойной клик на файле)
  2. Открыть список Data Sources ( Data > Show Data Sources )
Visual Studio автоматически добавила определенные domain context clas в список источников данных
Просто перетащите источник данных Customer на панель дизайнера и Visual Studio сделает все остальное.

Шаг шестой: Запуск
Если запустить приложение вы должны увидеть:
Это работает из-за того что когда вы переносите источник данных на страницу в дизайнере Visual Studio создает контролы DomainDataSource и DataGrid. На DomainDataSouce устанавливается свойство QueryName в "GetCustomersQuery" и на DataGrid свойство ItemsSource устанавливается на DomainDataSource
Сгенерированный код прибавляет Query в конец имени вашего метода. И именно в таком виде (GetCustomersQuery) его надо вызывать из UI у domain context class. Этот метод вызовет метод GetCustomers нашего Domain Service Class, который в свою очередь вызовет метод Retrive нашего бизнес-объекта.
Вот как это примерно выглядит:


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

Кулинария на каждый день или "Цель : покушать"

Жена уехала на пару дней на дачу. Решил что-нибудь приготовить покушать. Понял что готовить не умею совершенно. Пришло в голову что Гугл в помощь. И вот нашел : сайтик кулинария на каждый день . Вкусные и доступные в приготовлении рецепты которые может приготовить каждый (даже такой как я)

суббота, июля 24, 2010

Сексуальный травматизм

Согласно опубликованному The Daily Telegraph. рейтингу сексуального травматизма, каждый третий британец получает травмы во время секса. Одним из самых опасных мест для занятий сексом является диван. Коварство этого атрибута любой гостиной заключается в том, что пылкие любовники бросаются в объятия, не дождавшись окончания романтического ужина и не успев убрать за собой посуду. Осколки от бокалов и тарелок являются главными травмирующими факторами.
Не самыми удобными местами для занятия сексом также признаны: лестницы и подъезды, семейные автомобили, душевые кабинки, стулья, кухонные столы, туалеты и встроенные шкафы в офисе. Каждый десятый респондент рассказал о том, что он сам или его партнерша когда-либо падали с кровати, а каждый 50-й британец падал со стиральной машины. Самые распространенные травмы во время любовных игр - это растяжение мышц или сухожилий, травмы спины, "ковровые ожоги" (ссадины, возникающие от сильного трения тела о напольное покрытие), спазмы мышц шеи, повреждения локтей и коленных суставов, ушиб плеча, вывих колена, травмы запястья или лодыжки.
Энергичные любовники могут нанести серьезный материальный ущерб. Чаще всего они бьют посуду, ломают кровати, рамки для картин. Особо страстным британцам удалось проломить стену, дверь и сломать комод. Британцы оказались изобретательнее многих в вопросах сексуального травматизма. Проводимые ранее исследования в других странах мира показывали, что самой частой травмой в результате акта любви являются "потертости" половых органов. Довольно часты также различные травмы мужского полового члена: разрывы "уздечки", последствия укусов, вывихи и т.д. По мнению медиков, есть три основные причины сексуального травматизма: малоопытность, необузданность и чрезмерная изобретательность, связанная зачастую со стремлением партнеров (или одного из них) "делать, как в кино".

Отсуда

воскресенье, июля 18, 2010

Новая биржа ссылок

Появилась новая биржа ссылок. Блогерам - хорошее вознаграждение, а рекламодателям - удобная статистика и актуальные характеристики блогов Rotapost. При грамотном подходе позволят прикрепить регион к своему сайту. Также не забываем региональные сервисы раскрутки. Раскрутка сайта в Волгограде заняла у меня определенное время. Пока не воспользовался услугам такой сео компании

Линзы будущего или как создать Enchanted Reality



Enchanted Reality - термин используемый для обозначения технологии которая позволяет совмещать реальный мир и виртуальный. Примером может служить приложение Layar для Android  которое используя функции gps, компаса и камеры определяет местоположение и направление взгляда пользователя и позволяет на экране телефона видеть как поверх изображения видимого с камеры телефона накладываются пользовательские метки привязанные к определенным географическим координатам.
Основной проблемой на пути развития данной технологи стоит как ни странно интерфейс. А точнее его аппаратная часть - приходиться смотреть "сквозь" телефон, который пока еще является довольно громоздким устройством.Тем не менее Defense Advanced Research Projects Agency (DARPA, подразделение в составе Министерства обороны США) ведет исследования которые в будущем позволят обойти данную проблему. На основе того что человеческое тело готовый элемент  питания вырабатывающий кинетическую и термальную энергию, а так-же того что существуют материалы позволяющие преобразовать эту энергию в слабые токи планируется создать линзы-дисплеи одеваемые прямо на глаза.
(с) тут

ключ АКБ

"Мегафон" предоставит второй номер для одной SIM- карты


Московское отделение « Мегафона» начало предоставлять своим абонентам новую услугу под на одной SIM-карте, причём второй – городской телефонный номер в коде 499 – тоже сможет принимать входящие вызовы и SMS-сообщения. Дополнительный номер не будет иметь отдельного лицевого счёта – пополнение баланса будет осуществляться точно так же, как к этому привыкли абоненты. Стоимость звонка на московский номер будет работать в роуминге по всей территории России. Стоимость новой услуги составляет 250 рублей в месяц, а подключить её можно абсолютно бесплатно в любом из офисов продаж и обслуживания сети «Мегафон
 «Мегафон» предоставит второй номер для одной SIM-карты | Новости Hardware - 3DNews - Daily Digital Digest 

Язык роботов ROILA


Все кто когда-либо задумывался о робототехнике, представляет себя актуальность проблемы взаимодействия оператора с роботом. В текущий момент наиболее адекватным выбором является речь, но текущий уровень данной технологии не позволяет использовать для этой цели естественные языки. Тут-то и приходит на помощь ROILA (RObot Interaction LAnguage). Он создан на основе нескольких африканских языков, голландского и испанского. Прост для распознавания речи текущими средствами р включает в себя около 850 слов.
По материалам статьи: Почему людям придется учить язык роботов?

Необычные авто ( почти гаджеты)

Сегодня пока утром серфил по нету наткнулся на очень интересный сайт "Автомобили 2.0" посвященный концептам автомобилей. На этом сайте публикуются новости связанные с необычными автомобилями. Примеры авто попадающих на сайт в моем поста. 

Эпидемия счастья


Исследователи уже выяснили, что полнота, одиночество, курение и даже развод «заразны». Исследование "Эмоции как инфекционные болезни в больших социальных сетях" только подтвердило эти мысли. Подробнее смотреть тут:
Счастье и несчастье не только передаются, но и могут становиться эпидемиями

Хорошая новость для пользователей Google


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

суббота, июля 17, 2010

Небывалая мобильность интерфейсов комьютера

Студент Тони Старк изобрел лампу - в которой совмещены и проектор вывода интерфейса на любую поверхность и камера для распознания действий пользователя. С этим изобретением он выиграл Audi Innovation Challenge
http://www.youtube.com/watch?v=b45BpeVDx9w

среда, июля 14, 2010

Первичный анализ по проекту netBot


1. Структура системы должна быть полностью модульной. Т.е. каждый ключевой элемент системы (будь то драйвер устройства, модуль внутреннего представления иди часть конвеера обработки данных)
2. Робот должен иметь представление о своем составе и состоянии каждого из компонентов (внутренняя модель робота)
3. Система управления базируюется на событиях и обработка событий должна быть декларативной а обработчики событий расширяемыми.

Проект netBot - C# проект по управлению роботами

Объявляю о создании проекта посвященному робототехнике.
Проект - система позволяющая управлять роботом и писать алгоритмы для автономного управления роботом на языке C#.
Система должна включать в себя

  1. Подсистему общения с сенсорами
  2. Подсистему движения\позиционирования
  3. Подсистему компьютерного зрения
Так-же система должна включать в себя спецификацю на устройства\сенсоры и спецификацию на драйвера к этим устройствам.
Дальнейший анализ требований буду проводить здесь-же - в моем блоге

вторник, июля 13, 2010

Система ведения логов

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


Требования

  1. Конфигурация должна быть легкой
  2. Система должна быть легко расширяема
  3. Система должна предоставлять множественные способы вывода данных
  4. Система должна обладать возможностью перехвата необработанных исключений
  5. Система должна иметь статический и нестатический интерфейсы.

Архитектура



Принятые решения по архитектуре можно увидеть на приведенной ниже диаграмме: Структура классов


Интересные места


Перехват исключений
/// <summary>
/// Установить перехватчик исключений на заданный домен приложений
/// </summary>
/// <param name="dom"> </param>Домен для установки перехватчика
public void SetupIntercept( AppDomain dom )
{  
 dom.UnhandledException += ( s, e ) => {     
  Logger.Instance.Log(new LogMsg() {      
   Exception = (Exception)e.ExceptionObject, 
   Lvl = 100,
   Msg = "------ Unhandled Exception ------\n"
  }); 
 };

 dom.FirstChanceException += ( s, e ) => {
  Logger.Instance.Log(new LogMsg()
  {
   Exception = e.Exception,
   Lvl = 80,
   Msg = "------ First Chance Exception ------\n"
  }); 
 };
}

Дальнейшее развитие



  • Канал для записи данных в Базу данных
  • Канал позволяющий передавать сообщения на внешний сервер
  • Приложение - сервер логов


Если у вас есть вопросы - пишите. Исходники тут


C# 4.0 Новое в языке


Новые возможности .NET 4.0: C# 4.0

После выхода Visual Studio 2010 beta 1 - первым делом нужно разобраться, что же дает нового нам C# 4.0 (так как это мой основной язык программирования - для меня это является важным). Первым делом должен вам порекомендовать примеры C# 4.0, которые можно скачать отсюда (там же есть документ New Features in C# 4.0, которая послужила основой для этого топика). Документацию по .Net Framework 4.0 beta 1 можно посмотреть в MSDN. Дальше будут следовать мой небольшой опыт знакомства с новой версией .NET.

1. Dynamic Language Runtime

Изначально стоит взглянуть на следующую схему, иллюстрирующую архитектуру DLR: 
Именно! Теперь в .net можно еще и скриптовые языки использовать, такие как IronRuby и IronPython. Не думаю, что я буду этим пользоваться, но любителям экзотики предоставляю ссылки:
  • IronPython. - open-source проект на CodePlex.
  • IronRuby. - open-source проект на RubyForge.
Более того, предоставляется исходники DLR, при помощи которых вы, наверняка, сможете создать свой динамический язык для .NET, если вам это необходимо
Итак DLR включает в себя Expression Trees, которые просто являются представлением вызовов методов или бинарных операций в виде дерева, их функциональность можно посмотреть на следующем примере:
Expression<int, bool>> exprTree = num => num < 5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
               param.Name, left.Name, operation.NodeType, right.Value);
В этом примере мы сначала описываем лямбда выражение x=>x<5, а затем при помощи объектов от Expression Trees разбираем данное выражение.
Call Site caching в DLR - это, насколько я понимаю, и есть динамическое представление вызовов методов динамических объектов или операций над динамическим объектами. DLR кеширует характеристики объектов (о типах объектах), а так же об операции, и если данная операция уже была выполнена ранее, тогда всю необходимую информацию DLR получит уже из кеша (вот как то так).
И последнее в DLR это набор классов, интерфейсов: IDynamicMetaObjectProvider, DynamicMetaObject, DynamicObject и ExpandoObject. Давайте опять посмотрим на примере, как нам это может пригодиться, и зачем нам вообще нужен этот DLR:
class Test1
{
}
 
static void Main(string[] args)
{
  dynamic t = new Test1();
  string str = t.Hello(); // Error 1 
 
  dynamic d = 7.0;
  int i = d; // Error 2
}
На удивление данный код скомпилируется и запустится. Все дело в волшебном слове dynamic, оно нам позволяет вызывать любые по имени свойства или методы, а так же приводить объект к любому типу. Во время Runtime (выполнения кода) вылетят ошибки, Error 1: о том, что метод не найден, Error 2: о том, что double невозможно привести к int. Попробуем их исправить:  для исправления первой ошибки наш класс Test1 отнаследуем от типа System.Dynamic.DynamicObject и перегрузим один из методов, для исправления второй просто явно укажем преобразование типов:
class Test1 : DynamicObject
{
  public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  {
    if (binder.Name == "Hello")
    {
      result = "Test1 is Dynamic Object!";
      return true;
    }
    return base.TryInvokeMember(binder, args, out result);
  }
}
 
static void Main(string[] args)
{
  dynamic t = new Test1();
  string str = t.Hello(); 
 
  dynamic d = 7.0;
  int i = (int) d;
}
Теперь наш код будет работать. Переменная str получить значение "Test1 is dynamic object!", а значение 7.
Конечно, необязательно наследоваться от класса DynamicObject, можно отнаследоваться и от интерфейсаIDynamicMetaObjectProvider, но тогда нужно будет самому реализовывать метод  DynamicMetaObject GetMetaObject(Expression parameter), и более того реализовывать свой тип, унаследованный от DynamicMetaObject, ну в любом случае варианты есть - так что можно взять на вооружение.

2. Именованные и необязательные параметры в методах

Это достаточно простая функциональность и уже много где оговорена, она хорошо описана вот например тут (на русском языке одним из автором хабрахабра). Если парой слов, то это возможность устанавливать дефолтные значения у параметров методов, а так же возможность установки значения параметра по имени при вызове метода. В общем пример будет лучшим объяснением:
class Test1 
{
  public void Method(int a = 0, string b = "Hello", bool c = true)
  {
    Console.WriteLine("{0}, {1}, {2}", a, b, c);
  }
}
 
static void Main(string[] args)
{
  Test1 o = new Test1();
  // Вызовем по как обычно
  o.Method(1, "Hello", true);
  // А можно поменять порядок параметров
  o.Method(b: "hello", c: true, a: 1);
  // Можно вообще ничего не вызывать
  // (установлены значения по умолчанию у всех параметров)
  o.Method();
  // Можно определить только необходимые параметры
  o.Method(1, "Hello");
  // И не обязательно по порядку
  o.Method(c: false);
}
Теперь из- за переименование параметра метода, код может и не скомпилироваться, если кто-то использовал установку значения по имени, так что нужно быть аккуратнее. Я рад дефолтным значениям, и постараюсь не использовать функциональность именованных параметров.
В дополнение хочу сказать, что если все таки будет у класса Test1 метод void Method(int a), тогда при вызове o.Method(1)вызовится именно он, а не метод из примера с дефолтными значениями.

3. Возможности для COM Interop

DLR так же дал новые возможности для COM Interop, теперь  можно COM объекты определять как динамические (точнее они уже являются в большинстве своем динамического типа) и не приводить постоянно получаемые объекты к определенным типам для вызова методов или свойств.
excel.Cells[1, 1].Value = "Hello";
// вместо 
((Excel.Range)excel.Cells[1, 1]).Value2 = "Hello";
Данный пример взят из документа New Futures in C# 4.0 С одной стороны приятно, что теперь не нужно мучаться и находить к какому же типу нужно привести объект, чтобы вызвать его свойство или метод, но с другой стороны теряется IntelliSense.

4. Новое в generic

Теперь обогатился и generic новой функциональностью. Можно теперь у интерфейсов и у делегатов перед определением generic типов писать out и in, зачем это чуть дальше, а сначала рассмотрим пример.
При работе с generic часто хочется сделать что то типа такого:
IList<string> strings = new List<string>();
IList<object> objects = strings;
Но нельзя. Потому, что следом можно написать:
objects[0] = 5;
string s = strings[0];
То есть, изначально у нас был список строк, потом обозначили его как список объектов, и хотим уже работать с ним, как с объектами, устанавливая любой другой объект в него, хотя список до сих пор является списком строк.
Но, если вдуматься, то можно представить, что если бы список был только для чтения, то мы бы уже не смогли ничего нарушить, и там бы логика была ясна, потому следующий код на C# 4.0 будет работать:
IEnumerable<object> objects = strings;
Огромную полезность данная функциональность принесет в работе с linq, там часто возникают проблемы, что возвращаем объекты одного типа, а нужно получить список другого типа (базового).
Итак, как же такое стало возможным. Сначала рассмотрим слово out. Теперь интерфейс IEnumerable объявлен какIEnumerable, где out обозначает, что тип может быть использован только для возвращения значений, в другом случае компилятор будет ругаться, ну и более того это дает нам, что интерфейс IEnumerable так же есть и IEnumerable, если у есть возможность приведения типа к B, если на простом примере, то IEnumerable, есть теперь и IEnumerable. Вот пример:
public interface IEnumerable<out T> : IEnumerable
{
  IEnumerator GetEnumerator();
}
public interface IEnumerator<out T> : IEnumerator
{
  bool MoveNext();
  T Current { get; }
}
Есть еще слово in. Его так же можно использовать в описании generic делегатов и интерфейсов. Несет оно такую же смысл как и слово out, только в данному случае описанный тип можно использовать только в передаче параметров, вот пример:
public interface IComparer<in T>
{
  public int Compare(T left, T right);
}
То есть в данном случае, если IComparer может считаться и IComparer, потому как если уж он может сравнивать объекты типа object, то и string тоже может.
Так же, как я уже сказал, слова out и in можно применять и к интерфейсам, так, например:
public delegate TResult Func<in TArg, out TResult>(TArg arg);

Заключение

Так же в .NET 4.0 появилось много новвовведений, таких как  Lazy Initialiation - память под объект выделяется тогда, когда это действительно становится нужно. Появились новые типы, как например, BigInteger - теперь не нужно для лабораторных работ студентам писать свои классы для работы с большими числами ;), SortedSet - класс представляет собой самостоятельное балансированное дерево, которое сохраняет данные в отсортированном порядке после вставки, удаления и поиска. В общем, есть еще что изучать.