---
title: "أصلح java.lang.NullPointerException في Kotlin وAndroid من رسالته"
description: "يأتي java.lang.NullPointerException في Kotlin من !!، أو قيمة Java في نوع لا يقبل null، أو تحويل null، أو استدعاء من Java. أطلقناه بـ6 طرق على JDK 17 ونعرض الحل لكل رسالة."
canonical: "https://logbrew.co/ar/errors/nullpointerexception"
last_updated: "2026-11-10"
---

# أصلح java.lang.NullPointerException في Kotlin وAndroid من رسالته

يأتي `java.lang.NullPointerException` في Kotlin من `!!`، أو قيمة Java في نوع لا يقبل null، أو تحويل `null`، أو استدعاء من Java. أطلقناه بـ6 طرق على JDK 17 ونعرض الحل لكل رسالة.

اختُبر في 10 نوفمبر 2026 باستخدام Kotlin 2.4.0 وOpenJDK 17.0.18 وlogbrew-kotlin 0.2.3

بقلم [Furkan Erday](https://github.com/furkanerday). Furkan Erday مؤسس LogBrew، ويبني LogBrew كل يوم باستخدام Claude Code وCodex.

Canonical: https://logbrew.co/ar/errors/nullpointerexception

## ما تسمّيه كل رسالة `NullPointerException`

| ما فعله الكود | `NullPointerException` | الرسالة تسمّي السبب |
| --- | --- | --- |
| `order!!` على قيمة null | نعم | بلا رسالة |
| قيمة Java في `val` لا تقبل null | نعم | `getProperty(...) must not be null` |
| `null as String` | نعم | `null cannot be cast to non-null type` |
| `null` من Java في معامل Kotlin | نعم | `Parameter specified as non-null is null` |
| استدعاء دالة على `null` في Java | نعم | `Cannot invoke "String.length()"` |
| قراءة `lateinit` قبل ضبطها | `UninitializedPropertyAccessException` | `lateinit property keg has not been initialized` |

6 تجارب على JDK 17 مع Kotlin 2.4. الكوب الممتلئ في العمود الأول يعني `NullPointerException`، وفي العمود الثاني أن رسالته سمّت السبب.

## اقرأ الرسالة، ثم الإطار الأول

### اعثر على السطر في كودك أنت

يسمّي أول إطار مكدّس في حزمتك أنت الملف والسطر. عندما يحتوي التتبّع على قسم `Caused by:`، اقرأ الإطارات تحته أولًا. ثم تخبرك الرسالة أي حالة من الحالات الـ5 أدناه لديك.

### بلا رسالة، من `!!` على قيمة null

يرمي `!!` استثناء `NullPointerException` بلا رسالة، لذلك يعرض المسجّل الذي يطبع الرسالة بعد نقطتين `java.lang.NullPointerException: null`. السطر في الإطار الأول يحمل `!!`.

```bash
val order: String? = null
order!!.length
```

المخرجات

```text
java.lang.NullPointerException
	at NpeKt.main$lambda$0(Npe.kt:27)
```

### `must not be null` عندما دخلت قيمة Java في نوع لا يقبل null

تعيد دالة Java نوع منصة، ولا يتحقق Kotlin منه إلا عندما تضعه في متغير لا يقبل null. يسمّي `getProperty(...)` الاستدعاء الذي أعاد `null`.

```bash
val beer: String = System.getProperty("taproom.beer")
```

المخرجات

```text
java.lang.NullPointerException: getProperty(...) must not be null
	at NpeKt.main$lambda$1(Npe.kt:30)
```

### `Parameter specified as non-null is null` عندما مرّرت Java قيمة `null` إلى Kotlin

يتحقق Kotlin من كل معامل لا يقبل null في دالة عامة عند استدعائها، لذلك تفشل قيمة `null` من Java في أول سطر من الدالة. تسمّي الرسالة الدالة والمعامل.

```bash
// Kotlin
fun greet(name: String): Int = name.length

// Java
NpeKt.greet(null);
```

المخرجات

```text
java.lang.NullPointerException: Parameter specified as non-null is null: method NpeKt.greet, parameter name
	at NpeKt.greet(Npe.kt)
```

### `null cannot be cast to non-null type` بعد تحويل `null`

يرمي `as String` على `null` استثناءً. يعيد `as? String` القيمة `null` بدلًا من ذلك، وهذا ما حدث في تجربتنا، بلا استثناء.

```bash
val value: Any? = null
value as String
```

المخرجات

```text
java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
	at NpeKt.main$lambda$2(Npe.kt:35)
```

### `Cannot invoke` من استدعاء دالة على `null` في كود Java

منذ JDK 15 تسمّي Java الدالة والمتغير. يعني `<local0>` أن الصنف جُمّع دون `-g`، لذلك اسم المتغير مفقود. جمّع بـ`javac -g` لتراه. على Android يكتب وقت التشغيل `Attempt to invoke virtual method ... on a null object reference` بدلًا من ذلك.

```bash
String beer = null;
beer.length();
```

المخرجات

```text
java.lang.NullPointerException: Cannot invoke "String.length()" because "<local0>" is null
	at Caller.lengthOfNull(Caller.java:10)
```

## أصلحه في Kotlin وAndroid

### استبدل `!!` بقيمة بديلة أو فشل مسمّى

يعطي `?:` قيمة افتراضية أو يخرج من الدالة. يفشل `requireNotNull()` مع رسالة فورًا ويقول ما كان مفقودًا، فيشير الإطار الأول والرسالة معًا إلى السبب.

```bash
val order = orders[id] ?: return
val keg = requireNotNull(taps[id]) { "keg is not set for tap $id" }
```

المخرجات

```text
java.lang.IllegalArgumentException: keg is not set for tap 3
	at NpeKt.main$lambda$6(Npe.kt:48)
```

### أعلن النوع قابلًا لـnull عند حدود Java

أعطِ القيمة القادمة من Java نوعًا يقبل null، فيجبرك المصرّف على التعامل مع `null` قبل استخدامها. ضع على كود Java الخاص بك `@Nullable` و`@NonNull`، فيرى Kotlin نوعًا حقيقيًا بدلًا من نوع المنصة.

```bash
val beer: String? = System.getProperty("taproom.beer")
val name = beer ?: "house ale"
```

### دع محلّل JSON يفشل عند التحليل، لا لاحقًا

يمكن لمحلّل يبني الكائنات بالانعكاس أن يضع `null` في خاصية Kotlin لا تقبل null، فيظهر الاستثناء بعيدًا عن التحليل. أبلغ square/moshi#143 عن هذا في 2016. وأُغلق في يناير 2018 مع الإجابة باستخدام محوّل Kotlin، الذي يرفض الحقل المفقود الذي لا يقبل null.

### استخدم `lateinit` فقط للقيم التي تُضبط قبل أول استخدام

ترمي خاصية `lateinit` المقروءة قبل ضبطها `UninitializedPropertyAccessException`، لا `NullPointerException`. تحقق أولًا من `::keg.isInitialized`، أو استخدم `by lazy` عندما تستطيع حساب القيمة.

```bash
class Taproom {
    lateinit var keg: String
}

Taproom().keg.length
```

المخرجات

```text
kotlin.UninitializedPropertyAccessException: lateinit property keg has not been initialized
	at Taproom.getKeg(Npe.kt:6)
```

### أرسل الاستثناء مع مكدّسه إلى LogBrew

يرسل `captureThrowable()` في SDK Kotlin نوع الاستثناء وإطارات مكدّسه وسلسلة أسبابه، ويجمع LogBrew التكرارات في 1 مشكلة. تبقى الرسالة خارجًا ما لم تمرّر `includeMessage = true`. في تطبيقك، مرّر `HttpTransport()` إلى `flush()` بدلًا من ناقل التسجيل.

```bash
import co.logbrew.sdk.LogBrewAndroid
import co.logbrew.sdk.LogBrewClient
import co.logbrew.sdk.RecordingTransport

val transport = RecordingTransport.alwaysAccept()
val client = LogBrewClient.create(apiKey = System.getenv("LOGBREW_API_KEY"), sdkName = "logbrew-kotlin", sdkVersion = "0.2.3")
try {
    val beer: String = System.getProperty("taproom.beer")
    beer.length
} catch (e: NullPointerException) {
    LogBrewAndroid.captureThrowable(client, "evt_npe_1", "2026-11-10T09:00:00Z", e)
}
println(client.flush(transport))
```

المخرجات

```text
TransportResponse(statusCode=202, attempts=1)
```

## ما رأيناه في الاختبار

جمّعنا 1 ملف Kotlin و1 ملف Java مع Kotlin 2.4.0 على OpenJDK 17.0.18 وأطلقنا الاستثناء بـ6 طرق. أربع منها جاءت من كود Kotlin، مع `!!`، وقيمة Java في `val` لا تقبل null، و`as String` على `null`، وقيمة `null` مرّرتها Java إلى معامل Kotlin. الخامسة كانت استدعاء دالة على `null` في Java. والسادسة، قراءة `lateinit`، لم تكن `NullPointerException` أصلًا.

حالة `!!` وحدها لم تحمل رسالة. سمّت الـ4 الأخرى الاستدعاء أو المعامل أو النوع أو الدالة. قالت رسالة Java `<local0>` عن المتغير لأننا جمّعنا دون `-g`.

رمى `requireNotNull()` مع رسالة `IllegalArgumentException: keg is not set for tap 3` على السطر الذي كتبناه فيه. أعاد `as? String` القيمة `null` بلا استثناء.

## لماذا ما زال Kotlin يرمي NullPointerException

يرفض مصرّف Kotlin الاستدعاء على نوع يقبل null، لذلك لا يرمي كود Kotlin استثناء `NullPointerException` إلا حيث تطلب واحدًا. تعدّد وثائق أمان null الأسباب الوحيدة وهي `!!`، و`throw` صريح، و`this` غير مهيأ، والتشغيل البيني مع Java. وتحويل `null` بـ`as` يرميه أيضًا، كما تُظهر تجربتنا.

القيمة القادمة من Java لها نوع منصة، يُكتب `String!` في رسائل المصرّف. يمكنك وضعها في `String` أو `String?`. في `String` يتحقق Kotlin منها عند الإسناد ويرمي `must not be null`، وهناك فشلت تجربتنا الثانية.

أضاف JEP 358 الرسالة `Cannot invoke ... because ... is null` إلى JVM في JDK 14، وفعّلها JDK 15 افتراضيًا. يكتب وقت تشغيل Android نصه الخاص. يعرضها google/gson#1778 من تطبيق Android بصيغة `Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference`.

## ما يسجّله LogBrew

أرسل `captureThrowable()` 1 مشكلة بعنوان `NullPointerException` بالمستوى `error`، مع `exception.type` بقيمة `NullPointerException`، والآلية `android.exception`، و`handled: true`. حملت سلسلة الأسباب 1 مدخلًا لـ`java.lang.NullPointerException` مع 7 إطارات مكدّس، لكل منها ملفه وسطره ودالته ووحدته. كان الإطار الأول `main` في `Npe.kt` عند السطر 58.

كانت الرسالة غائبة، وقال مدخل السلسلة `messageState: "redacted"`. مع `includeMessage = true` حملت المشكلة `getProperty(...) must not be null` رسالةً لها. ومع `includeStackTrace = true` حمل حقل البيانات الوصفية `throwableStackTrace` نص التتبّع دون الرسالة.

أجاب `flush()` بـ`statusCode=202, attempts=1` عبر ناقل التسجيل. ويذهب الجسم نفسه إلى LogBrew عندما تمرّر `HttpTransport()`.

## أسئلة شائعة

### ما هو NullPointerException؟

الاستثناء الذي ترميه JVM عندما يستخدم الكود مرجعًا يحمل `null` في استدعاء دالة أو قراءة حقل أو فهرس مصفوفة أو فك تغليف. يرث `RuntimeException`، لذلك لا تسمّيه أي عبارة `throws`.

### لماذا يرمي Kotlin استثناء NullPointerException رغم أمان null فيه؟

يتحقق Kotlin من قابلية null وقت التصريف لأنواع Kotlin فقط. أما `!!`، و`as` على `null`، وقيمة Java تضعها في نوع لا يقبل null، واستدعاء من Java يمرّر `null`، فكلها ترمي الاستثناء وقت التشغيل. ولكل منها رسالته الخاصة، المذكورة أعلاه.

### ماذا يعني `java.lang.NullPointerException: null`؟

الاستثناء بلا رسالة. الكود الذي يطبع الرسالة بعد نقطتين يكتب `null` هناك. في Kotlin يرمي `!!` هذا الاستثناء بالضبط، فابحث عن `!!` في السطر في الإطار الأول.

### ماذا يعني Parameter specified as non-null is null؟

مرّرت Java، أو الانعكاس، قيمة `null` إلى دالة Kotlin معاملها لا يقبل null. تسمّي الرسالة الدالة والمعامل. اجعل المعامل يقبل null، أو أوقف `null` من جهة المستدعي.

### كيف أصلح NullPointerException في Android؟

اقرأ الإطار تحت `Caused by:` الذي يقع في حزمتك، ثم طابق الرسالة مع الحالات أعلاه. في Android يكتب وقت التشغيل `Attempt to invoke virtual method ... on a null object reference`، والدالة التي يسمّيها هي الاستدعاء على `null`.

### هل NullPointerException استثناء مفحوص؟

لا. يرث `RuntimeException`، لذلك لا يجبرك المصرّف على التقاطه. أصلح السبب بدلًا من التقاطه، لأن `null` الذي يصل إلى استدعاء دالة خطأ في الكود الذي قبله.

## اعرف كل NullPointerException مع مكدّسه

يرسل SDK Kotlin من LogBrew كل استثناء مع نوعه وإطارات مكدّسه وسلسلة أسبابه، ويجمع LogBrew التكرارات في 1 مشكلة. ابدأ بخطة مجانية سخية دون بطاقة.

[ابدأ مجانًا](https://logbrew.co/ar)

## المصادر

- [Kotlin docs, Null safety](https://kotlinlang.org/docs/null-safety.html)
- [Kotlin docs, Null-safety and platform types](https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types)
- [JEP 358, Helpful NullPointerExceptions](https://openjdk.org/jeps/358)
- [square/moshi#143](https://github.com/square/moshi/issues/143)
- [google/gson#1778](https://github.com/google/gson/issues/1778)

## المزيد من حلول الأخطاء

- [أصلح خطأ Script error الذي يخفي رسالته وملفه وسطره](https://logbrew.co/ar/errors/script-error)
- [أصلح خطأ Failed to fetch وميّز بين أسبابه الـ3](https://logbrew.co/ar/errors/failed-to-fetch)
- [أخطاء أعدنا إنتاجها، وكيف تصلح كلًا منها](https://logbrew.co/ar/errors)
