Java 7 رسمياً

Java7graphic

يوم السبت الماضي 9/7/2011 كان أحد فعاليات انطلاق Java 7 رسمياً هذه الأيام فقد أطلقت Oracle النسخة النهائية للـ Java 7 في 7-7-2011 وتبعه العديد من الأحداث و الاجتماعات التي تشرح جديد Java 7.

egjug_logo

منظمو اليوم هم EGJUG الذين بذلوا جهداً مشكوراّ لتقديم هذا الحدث (شكراً EGJUG) .

Simon_Ritter

كان هذا الحدث في الجامعة الأمريكية بحضور Simon Ritter من Oracle والذي قدّم ثلاث محاضرات تكلّم فيها عن جديد الـ Java 7 SE و الأخرى عن الـ Garbage Collector والثالثة عن الـ Java FX .

Sherif Aly
Simon Ritter -
Technology Evangelist

 

  بالإضافة إلى محاضرة من الدكتور شريف علي الأستاذ بالجامعة الأمريكية 
  والتي كانت بعنوان Rethinking Computing .

 

 

نأتي لأهم ما تم مناقشته في جديد Java 7 :

أولاً: Binary Literals

في Javas 7 SE يمكن التعبير عن integral types مثل (byte, short, int, and long) بالنظام binary ، لكن يجب عليك قبل استعماله أن تضيف 0b أو 0B للرقم. كالمثال التالي :

 

//An 8-bit 'byte' value:
byte aByte = (byte)0b00100001;

// A 16-bit 'short' value:
short aShort = (short)0b1010000101000101;

// Some 32-bit 'int' values:
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.

// A 64-bit 'long' value. Note the "L" suffix:
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
ثانياً: Underscores in Numeric Literals
في الـ Java SE 7 وما بعدها يمكن أن تجد الحرف (_) بين خانات الأرقام ، هذه الخاصية تتيح لك تقسيم الرقم إلى مجموعات لسهولة القراءة.
على سبيل المثال لو أن الكود يحتوى على رقم متعدد الخانات –رقم كبير- يمكنك أن تستخدم الـ (_) لتفصل الرقم إلى مجموعات كما يعبر البعض عنها من خلال إضافة علامات الترقيم كـ comma أو space أو separator. المثال التالي يوضح كيفية استخدام الـ (_).
long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 	3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;
ملحوظة: يمكنك إضافة الـ (_) بين الأرقام فقط ولا يمكن إضافتها في الأماكن التالية:
  1. في بداية أو نهاية أي رقم.
  2. أن تضعها بجوار العلامية العشرية في الأرقام العشرية.
  3. قبل الرمز F أو L.
  4. في أماكن متوقع أن تكون String وليست رقم.
الأمثلة التالية توضح الخطأ و الصواب في استخدام هذه الميزة الجديدة:
float pi1 = 3_.1415F;
// Invalid; cannot put underscores adjacent to a decimal point float pi2 = 3._1415F;
// Invalid; cannot put underscores adjacent to a decimal point long socialSecurityNumber1 = 999_99_9999_L;
// Invalid; cannot put underscores prior to an L suffix
int x1 = _52;
// This is an identifier, not a numeric literal int x2 = 5_2;
// OK (decimal literal)
int x3 = 52_;
// Invalid; cannot put underscores at the end of a literal
int x4 = 5_______2;
// OK (decimal literal)
int x5 = 0_x52;
// Invalid; cannot put underscores in the 0x radix prefix
int x6 = 0x_52;
// Invalid; cannot put underscores at the beginning of a number
int x7 = 0x5_2;
// OK (hexadecimal literal)
int x8 = 0x52_;
// Invalid; cannot put underscores at the end of a number
int x9 = 0_52;
// OK (octal literal) int x10 = 05_2;
// OK (octal literal)
int x11 = 052_;
// Invalid; cannot put underscores at the end of a number
ثالثاً: Strings in switch Statements
في JDK 7 يمكنك استخدام String في جملة switch.
public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
     String typeOfDay;
     switch (dayOfWeekArg) {
         case "Monday":
             typeOfDay = "Start of work week";
             break;
         case "Tuesday":
         case "Wednesday":
         case "Thursday":
             typeOfDay = "Midweek";
             break;
         case "Friday":
             typeOfDay = "End of work week";
             break;
         case "Saturday":
         case "Sunday":
             typeOfDay = "Weekend";
             break;
         default:
             throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
     }
     return typeOfDay;
}
 تتم مقارنة String object الموجود في بداية جملة الـ switch مع كل case label وكأنك تستخدم String.equals method . مما يوفر على المطور الحلول الأخرى كاستخدام if-then-else.
رابعاً:
Type Inference for Generic Instance Creation
 حين تعريف متغير لـ object مستخدماً الخاصية generic ، لم يعد ضرورياً كتابة نوع محتوى الـ object مرتين (في الـ declaration و intitialization) ، تنادي فقط على الـ constructor للـ generic class وبجوارها العلامة (<>) ويقوم الـ compiler تلقائياً بالتعرف على الأنواع التي عرّفتها في بداية الجملة في (declaration)

يطلق على الرمز (<>) الاسم diamond ، على سبيل المثال:

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

في الـ Java SE 7 يمكنك التعويض عن الأنواع المعرّفة بجوار الـ constructor بالرمز (<>):

Map<String, List<String>> myMap = new HashMap<>();

إذا لم يتم إضافة (<>) سيقوم الـ compiler بعمل unchecked conversion warning
لأن الـ HashMap() constructor ستشير إلى HashMap raw
وليس Map<String, List<String>> type

Map<String, List<String>> myMap = new HashMap();
// unchecked conversion warning
Java SE 7 تدعم استنتاج الأنواع -type inference- بشكل محدود ، يمكنك استخدام هذه الخاصية فقط لو أن الـ parameterized type للـ constructor واضح من خلال السياق ، على سبيل المثال هذا الكود لن يتم عمل compile له :

List<String> list = new ArrayList<>();
list.add("A");

  // The following statement should fail since addAll expects
  // Collection<? extends String>
list.addAll(new ArrayList<>());

لاحظ أن الـ diamond تعمل في method calls على الرغم من أن المعتاد استخدامها في الـ  declarations ، مثال على ذلك :

// The following statements compile:

List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
لاحظ أن الـ constructor يمكن أن يكون generic في كل من generic classes أو non-generic classes ، كما في المثال التالي :
class MyClass<X> {
  <T> MyClass(T t) {
    // ...
  }
}
لاحظ عند عمل instantiation للـ MyClass وهي كود سليم في كل من Java SE 7 وما قبلها:
new MyClass<Integer>("")

هذه الجملة تنشيء object من MyClass<Integer>; وتجعل الـ formal type parameter, X يكون من النوع Integer للـ generic class MyClass<X>i لاحظ أن هذا الـ generic class يحتوي على formal type parameter, T آخر ، الـ compiler تلقائياً يستنتج النوع String للـ formal type parameter, T الخاص بالـ constructor لهذا الـ class لأن ما دخل إلى الـ constructor هو String object .

الـ Compilers في الإصدارات السابقة لـ Java SE 7 كانت تستطيع استنتاج الـ actual type parameters of generic constructors كـ generic methods ، على الرغم من ذلك الـ compiler في Java SE 7 يمكنه استنتاج actual type parameters of the generic class being instantiated لو استخدمت (<>) ، كما في المثالين التاليين:

* MyClass<Integer> myObject = new MyClass<>("");
في هذا المثال الـ compiler يستنتج النوع Integer للـ formal type parameter, X الخاص بالـ generic class MyClass<X>i. كما يستنتج النوع String للـ formal type parameter, T الخاص بالـ constructor .
* MyClass<Integer> myObject = new <String> MyClass<>("");
في هذا المثال الـ compiler يستنتج النوع Integer للـ formal type parameter, X الخاص بالـ generic class MyClass<X>i. وتم تحديد النوع String بشكل explicitly للـ formal type parameter, T الخاص بالـ constructor .
خامساً:

The try-with-resources Statement

جملة الـ try-with-resources هي جملة try والتي تعرف واحد أو أكثر من الـ resources. الـ resource هو الـ object الذي من الضروري أن بغلقه البرنامج بعد الانتهاء.

جملة الـ try-with-resources تتأكد من أن كل resource تم غلقه ، أي object بيـ object implement الـ java.lang.AutoCloseable أو java.io.Closeable يمكن استخدامه كـ resource.

هذا المثال يقرأ أو سطر من ملف ، يستخدم الـ BufferedReader لقراءة البيانات من الملف. BufferedReader عبارة عن resource والذي يجب بتم غلقه بعد انتهاء البرنامج منه.

static String readFirstLineFromFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}

في هذا المثال تم تعريف الـ resource في جملة الـ try-with-resources عبارة عن BufferedReader.

ولأن الـ BufferedReader instance تم تعريفها داخل الـ try وهذه الـ class بتـ implement الـ interface java.lang.AutoCloseable. سيتم غلقها بمجرد أن تنتهي الجمل داخل الـ  try.

قبل الـ Java SE 7 كنا نستخدم finally block لنتأكد من إغلاق الـ resource، المثال التالي يستخدم الـ finally block بدلاً من الـ try-with-resources .

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    return br.readLine();
  } finally {
    if (br != null) br.close();
  }
}

يمكنك تعريف واحد أو أكثر من الـ resources داخل جملة الـ  try-with-resources ، في المثال التالي يستعيد أسماء الملفات المضغوطة داهل الملف zipFileName  وينشيء ملف text يحوي تلك الأسماء.

public static void writeToFileZipFileContents(String zipFileName, String outputFileName)
    throws java.io.IOException {

    java.nio.charset.Charset charset = java.nio.charset.Charset.forName("US-ASCII");
    java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with try-with-resources statement

    try (
      java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
      java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {

      // Enumerate each entry

      for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {

        // Get the entry name and write it to the output file

        String newLine = System.getProperty("line.separator");
        String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
        writer.write(zipEntryName, 0, zipEntryName.length());
      }
    }
  }

في هذا المثال جملة الـ try-with-resources تم تعريف ZipFile و BufferedWriter مفصولين بـ semicolon. بعد الانتهاء من هذا الكود يتم تلقئياً استدعاء الـ close methods لكل من الـBufferedWriter و ZipFile.

سادساً:

Catching Multiple Exception Types

في الـ Java SE 7 وما بعدها catch block واحد يمكن أن يعالج أكثر من exception مما يساعد على تقليل تكرار الكود ، المثال التالي يوضح ذلك :

catch (IOException ex) {
     logger.log(ex);
     throw ex;
catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

الحل لهذا الكود في الـ Java SE 7  كالتالي:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}
وبالتالي يتم إلغاء التكرار حيث كان قبل الـ Java SE 7 كان من الصعب إنشاء common method لإلغاء التكرار حيث المتغير ex مختلف.
كانت هذه بعض الخصائص الجديدة في الـ Java SE 7. جهد متواضع لتقديم المعلومة لكن هناك الكثير من التفاصيل على موقع Oracle بمكنك الاطلاع عليها.
------------------------------------------------

المصادر: Java SE 7 Documentation

ليست هناك تعليقات:

إرسال تعليق

---- أتشرف بتعليقاتكم ----