۳۰ آذر ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

نحوه استفاده از اظهارات در جاوا

از اظهارات جاوا برای آزمایش فرضیات خود در مورد صحت برنامه و بررسی آنها در کد خود استفاده کنید.

از اظهارات جاوا برای آزمایش فرضیات خود در مورد صحت برنامه و بررسی آنها در کد خود استفاده کنید.

توسعه دهندگان در مورد نحوه عملکرد کد ما هنگام اجرا فرضیاتی دارند، اما همیشه حق با ما نیست. بدون قطعیت، نوشتن برنامه هایی که در زمان اجرا به درستی کار می کنند چالش برانگیز است. ادعاهای جاوا یک راه نسبتا آسان برای تأیید درستی منطق برنامه نویسی شما ارائه می دهد.

آنچه در این آموزش جاوا خواهید آموخت

در این مقاله، می آموزید که ادعاها چیست، چگونه آنها را بنویسید، و چگونه از آنها در برنامه های جاوا خود استفاده کنید:

  • اظهارات جاوا چیست؟
  • نحوه نوشتن یک ادعا در جاوا
  • اظهارات با پیش شرط و پیش شرط
  • تفاوت بین ادعاهای جاوا و استثناهای جاوا

اظهارات جاوا چیست؟

قبل از JDK ۱.۴، توسعه دهندگان اغلب از نظرات برای مستندسازی مفروضات مربوط به صحت برنامه استفاده می کردند. اما نظرات در واقع به ما کمک نمی‌کنند تا فرضیات خود را آزمایش و اشکال‌زدایی کنیم. کامپایلر نظرات را نادیده می گیرد، بنابراین راهی برای استفاده از آنها برای تشخیص باگ وجود ندارد. توسعه دهندگان همچنین اغلب نظرات را هنگام تغییر کد به روز نمی کنند.  

در JDK 1.4، ادعاها به عنوان مکانیزم جدیدی برای آزمایش و اشکال زدایی مفروضات مربوط به کد جاوا معرفی شدند. در اصل، اظهارها موجودیت های قابل کامپایل هستند که در زمان اجرا اجرا می شوند، با این فرض که آنها را برای آزمایش برنامه فعال کرده اید. می‌توانید اظهارات را برنامه‌ریزی کنید تا شما را از اشکال‌هایی که در آن‌ها رخ می‌دهند مطلع کنند، و مدت زمانی را که در غیر این صورت برای اشکال‌زدایی یک برنامه ناموفق صرف می‌کنید تا حد زیادی کاهش می‌دهد.

اظهارها برای کدگذاری الزاماتی استفاده می‌شوند که یک برنامه را با آزمایش شرایط (عبارات بولی) برای مقادیر واقعی، و اطلاع دادن به توسعه‌دهنده در صورت نادرست بودن چنین شرایطی، صحیح یا نادرست می‌سازد. استفاده از اظهارات می تواند تا حد زیادی اعتماد شما را به صحت کدتان افزایش دهد.

نحوه نوشتن یک ادعا در جاوا

ادعاها از طریق عبارت assert و کلاس java.lang.AssertionError پیاده سازی می شوند. این عبارت با کلمه کلیدی assert شروع می شود و با عبارت Boolean ادامه می یابد. به صورت نحوی به صورت زیر بیان می شود:


assert BooleanExpr;

اگر BooleanExpr به درستی ارزیابی شود، هیچ اتفاقی نمی‌افتد و اجرا ادامه می‌یابد. اگر عبارت نادرست ارزیابی شود، همانطور که در فهرست ۱ نشان داده شده است، AssertionError نمونه سازی می شود و پرتاب می شود.


public class AssertDemo
{
   public static void main(String[] args)
   {
      int x = -1;
      assert x >= 0;
   }
}

اظهار در فهرست ۱ نشان‌دهنده اعتقاد توسعه‌دهنده است که متغیر x حاوی مقداری بزرگ‌تر یا مساوی ۰ است. با این حال، واضح است که چنین نیست. اجرای دستور assert منجر به یک AssertionError پرتاب می شود.

فهرست ۱ (javac AssertDemo.java) را کامپایل کنید و آن را با اظهارات فعال اجرا کنید (java -ea AssertDemo). شما باید خروجی زیر را مشاهده کنید:


Exception in thread "main" java.lang.AssertionError
        at AssertDemo.main(AssertDemo.java:6)

این پیام تا حدی رمزآلود است زیرا مشخص نمی کند که چه چیزی باعث پرتاب AssertionError شده است. اگر پیام آموزنده‌تری می‌خواهید، از عبارت assert زیر استفاده کنید:


assert BooleanExpr : expr;

در اینجا، expr هر عبارتی است (از جمله فراخوانی متد) که می‌تواند مقداری را برگرداند—شما نمی‌توانید متدی را با نوع بازگشت void فراخوانی کنید. یک عبارت مفید، رشته ای است که دلیل شکست را توضیح می دهد، همانطور که در فهرست ۲ نشان داده شده است.


public class AssertDemo
{
   public static void main(String[] args)
   {
      int x = -1;
      assert x >= 0: "x < 0";
   }
}

فهرست ۲ (javac AssertDemo.java) را کامپایل کنید و آن را با اظهارات فعال اجرا کنید (java -ea AssertDemo). این بار، باید خروجی کمی گسترش یافته زیر را مشاهده کنید، که شامل دلیل پرتاب AssertionError است:


Exception in thread "main" java.lang.AssertionError: x < 0
        at AssertDemo.main(AssertDemo.java:6)

برای هر یک از مثال‌ها، اجرای AssertDemo بدون گزینه -ea (فعال کردن ادعاها) هیچ خروجی ندارد. وقتی ادعاها فعال نمی شوند، اجرا نمی شوند، اگرچه هنوز در فایل کلاس وجود دارند.

JetBrains نسل بعدی Fleet IDE را پیش‌نمایش می‌کند

ادعاهای با پیش شرط و پس شرط

مفروضات یک برنامه را با تأیید اینکه پیش‌شرط‌ها و شرایط پس از آن نقض نمی‌شوند، مفروضات برنامه را آزمایش می‌کنند و در صورت وقوع تخلف به برنامه‌نویس هشدار می‌دهند:

  • یک پیش شرط شرطی است که باید قبل از اجرای برخی از دنباله کد به درستی ارزیابی شود. پیش شرط ها تضمین می کند که تماس گیرندگان قرارداد خود را با تماس گیرندگان حفظ می کنند.
  • یک postcondition شرطی است که باید پس از اجرای یک سری کد به درستی ارزیابی شود. شرایط پست تضمین می کند که تماس گیرندگان قرارداد خود را با تماس گیرندگان حفظ می کنند.

پیش‌شرط‌های نوشتن

شما می‌توانید با بررسی صریح و استثناء در صورت لزوم، پیش‌شرط‌ها را روی سازنده‌ها و متدهای عمومی اعمال کنید. برای روش‌های کمکی خصوصی، می‌توانید پیش‌شرط‌ها را با مشخص کردن ادعاها اعمال کنید. مثال فهرست ۳ را در نظر بگیرید.


import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

class PNG
{
   /**
    *  Create a PNG instance, read specified PNG file, and decode
    *  it into suitable structures.
    *
    *  @param filespec path and name of PNG file to read
    *
    *  @throws NullPointerException when <code>filespec</code> is
    *          <code>null</code>
    */
   PNG(String filespec) throws IOException
   {
      // Enforce preconditions in non-private constructors and
      // methods.

      if (filespec == null)
         throw new NullPointerException("filespec is null");
      try (FileInputStream fis = new FileInputStream(filespec))
      {
         readHeader(fis);
      }
   }

   private void readHeader(InputStream is) throws IOException
   {
      // Confirm that precondition is satisfied in private
      // helper methods.

      assert is != null : "null passed to is";
   }
}

public class AssertDemo
{
   public static void main(String[] args) throws IOException
   {
      PNG png = new PNG((args.length == 0) ? null : args[0]);
   }
}

کلاس PNG در فهرست ۳، حداقل شروع یک کتابخانه برای خواندن و رمزگشایی فایل های تصویری PNG است. سازنده صراحتاً filespec را با null مقایسه می‌کند و زمانی که این پارامتر حاوی null باشد، NullPointerException را پرتاب می‌کند. نکته این است که این پیش شرط را اعمال کنیم که filespec حاوی null نباشد.

استودیو Vertex AI این وعده را در هوش مصنوعی مولد می دهد

تعیین assert filespec != null; مناسب نیست زیرا پیش شرط ذکر شده در Javadoc سازنده (از لحاظ فنی) در هنگام غیرفعال شدن ادعاها رعایت نمی شود. (در واقع، افتخار می شود زیرا FileInputStream() NullPointerException را پرتاب می کند، اما شما نباید به رفتار غیرمستند وابسته باشید.)

با این حال، assert در زمینه روش کمکی خصوصی readHeader() مناسب است، که در نهایت برای خواندن و رمزگشایی هدر ۸ بایتی یک فایل PNG تکمیل خواهد شد. . پیش شرط اینکه is همیشه یک مقدار غیر تهی ارسال شود، همیشه باقی خواهد ماند.

نوشتن شرایط پست

شرایط پسا معمولاً از طریق اظهارنظرها مشخص می‌شوند، صرف نظر از عمومی بودن یا نبودن روش (یا سازنده). مثال فهرست ۴ را در نظر بگیرید.


public class AssertDemo
{
   public static void main(String[] args)
   {
      int[] array = { 20, 91, -6, 16, 0, 7, 51, 42, 3, 1 };
      sort(array);
      for (int element: array)
         System.out.printf("%d ", element);
      System.out.println();
   }

   private static boolean isSorted(int[] x)
   {
      for (int i = 0; i < x.length - 1; i++)
         if (x[i] > x[i + 1])
            return false;
      return true;
   }

   private static void sort(int[] x)
   {
      int j, a;
      // For all integer values except the leftmost value ...
      for (int i = 1; i < x.length; i++)
      {
         // Get integer value a.
         a = x[i];
         // Get index of a. This is the initial insert position, which is
         // used if a is larger than all values in the sorted section.
         j = i;
         // While values exist to the left of a's insert position and the
         // value immediately to the left of that insert position is
         // numerically greater than a's value ...
         while (j > 0 && x[j - 1] > a)
         {
            // Shift left value -- x[j - 1] -- one position to its right --
            // x[j].
            x[j] = x[j - 1];
            // Update insert position to shifted value's original position
            // (one position to the left).
            j--;
         }
         // Insert a at insert position (which is either the initial insert
         // position or the final insert position), where a is greater than
         // or equal to all values to its left.
         x[j] = a;
      }

      assert isSorted(x): "array not sorted";
   }
}

فهرست ۴ یک روش کمکی sort() را ارائه می‌کند که از الگوریتم مرتب‌سازی درج برای مرتب‌سازی آرایه‌ای از مقادیر صحیح استفاده می‌کند. من از assert برای بررسی اینکه x مرتب شده است قبل از اینکه sort() به تماس گیرنده خود برگردد، مرتب شده است.

استفاده کرده ام.

مثال در فهرست ۴ یک ویژگی مهم ادعاها را نشان می دهد، و آن این است که اجرای آنها معمولاً گران هستند. به همین دلیل، ادعاها معمولاً در کد تولید غیرفعال می شوند. در فهرست ۴، isSorted() باید کل آرایه را اسکن کند، که در مورد یک آرایه طولانی می تواند زمان بر باشد.

ادعاها در مقابل استثناها در جاوا

توسعه‌دهندگان از اظهارات برای مستندسازی موقعیت‌های غیرممکن منطقی و شناسایی خطاها در منطق برنامه‌نویسی خود استفاده می‌کنند. در زمان اجرا، یک ادعای فعال به توسعه‌دهنده یک خطای منطقی هشدار می‌دهد. توسعه‌دهنده کد منبع را تغییر می‌دهد تا خطای منطقی را برطرف کند و سپس این کد را دوباره کامپایل می‌کند.

Node.js 22 وارد می شود، ماژول های ECMAScript را پشتیبانی می کند

توسعه‌دهندگان از مکانیسم استثنا جاوا برای پاسخ به خطاهای زمان اجرا غیرمرگبار مانند تمام شدن حافظه استفاده می‌کنند. چنین خطاهایی ممکن است به دلیل عوامل محیطی مانند فایلی که وجود ندارد، یا به دلیل کد نوشته شده ضعیف، مانند تلاش برای تقسیم بر ۰ ایجاد شود. یک کنترل کننده استثنا اغلب برای بازیابی دلپذیر از خطا نوشته می شود تا برنامه بتواند به اجرای خود ادامه دهد. .

اظهارها جایگزین استثناها نیستند. برخلاف استثناها، ادعاها از بازیابی خطا پشتیبانی نمی‌کنند (اظهارات معمولاً اجرای برنامه را فوراً متوقف می‌کنند—AssertionError قرار نیست شناسایی شود). آنها اغلب در کد تولید غیرفعال هستند. و معمولاً پیام‌های خطای کاربرپسند را نمایش نمی‌دهند (اگرچه این مشکل با assert نیست). مهم است که بدانید چه زمانی از استثناها به جای ادعاها استفاده کنید.

زمان استفاده از استثناها

فرض کنید یک روش sqrt() نوشته اید که جذر آرگومان خود را محاسبه می کند. در یک بافت اعداد غیر مختلط، گرفتن جذر یک عدد منفی غیرممکن است. بنابراین، اگر آرگومان منفی باشد، از یک ادعا برای شکست روش استفاده می‌کنید. قطعه کد زیر را در نظر بگیرید:


public double sqrt(double x)
{
   assert x >= 0 : "x is negative";
   // ...
}

استفاده از یک ادعا برای تأیید اعتبار آرگومان در این روش public نامناسب است. یک ادعا برای شناسایی خطاها در منطق برنامه نویسی و نه محافظت از یک روش در برابر استدلال های اشتباه در نظر گرفته شده است. علاوه بر این، اگر ادعاها غیرفعال شوند، راهی برای مقابله با مشکل استدلال منفی وجود ندارد. بهتر است یک استثنا به صورت زیر ایجاد کنید:


public double sqrt(double x)
{
   if (x < 0)
      throw new IllegalArgumentException("x is negative");
   // ...
}

توسعه‌دهنده ممکن است تصمیم بگیرد که برنامه استثناء آرگومان غیرقانونی را مدیریت کند، یا به سادگی آن را در خارج از برنامه منتشر کند، جایی که یک پیام خطا توسط ابزار اجرای برنامه نمایش داده می‌شود. هنگامی که آنها پیام خطا را می‌خوانند، توسعه‌دهنده می‌تواند هر کدی که منجر به استثنا شده است را برطرف کند.

شاید متوجه تفاوت ظریف بین ادعا و منطق تشخیص خطا شده باشید. اصرار x >= ۰ را آزمایش می کند، در حالی که منطق تشخیص خطا x < 0 را آزمایش می کند. این ادعا خوش بینانه است: ما فرض می کنیم که استدلال درست است. در مقابل، منطق تشخیص خطا بدبینانه است: ما فرض می کنیم که استدلال درست نیست. ادعاها منطق صحیح را مستند می کنند، در حالی که استثناها رفتار زمان اجرا نادرست را نشان می دهند.

نتیجه گیری

در این آموزش یاد گرفتید که چگونه از ادعاها برای مستندسازی منطق صحیح برنامه استفاده کنید. همچنین یاد گرفته‌اید که چرا ادعاها جایگزین استثناها نیستند، و مثالی را مشاهده کرده‌اید که در آن استفاده از یک استثنا مؤثرتر است.

بعد بخوانید: استثناها در جاوا: نحوه پرتاب، امتحان و گرفتن استثناهای جاوا