惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LangChain Blog
WordPress大学
WordPress大学
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
MyScale Blog
MyScale Blog
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
P
Proofpoint News Feed
D
DataBreaches.Net

Inside Nutrient

A guide to the invisible work behind documents Introducing Nutrient Documents for Salesforce: Native document generation and signing Document AI vs. traditional OCR: Choosing between OCR, AI, and hybrid pipelines PDF SDK compliance and security evaluation checklist for enterprise teams (2026) Invariant Corp replaces paper processes with Nutrient Workflow and scales without limits What is process mapping? A complete guide Nutrient vs. Conga Composer for Salesforce document generation (2026) Document routing: How to automate document distribution The CTO’s AI playbook: Why accountability architecture beats orchestration Compliance workflow automation: Why built-in compliance is table stakes Workflow diagrams: Examples, symbols, and how to build one that actually runs Digital forms: Replace paper forms with automated workflows Approval workflow software: How to automate approvals Why document-centric automation is different The CEO’s AI playbook: Why decision architecture beats model selection Nutrient SDK product updates for Q1 2026 PDF redaction verification: How to prove sensitive data is permanently removed What is a VPAT? The complete guide to accessibility conformance reports What is PDF/UA? The accessible PDF standard explained Salesforce eSignatures: Generate, sign, and track documents in one flow Online document viewer: Options, tradeoffs, and how to embed one Document viewer for web apps: React, Vue, Angular (2026) Best document viewers in 2026: A buyer’s guide How to edit a PDF in Python: Add text, images, and annotations Nutrient advances Workflow platform with agentic AI for enterprise-grade speed and consistency in document-heavy operations How to create a Salesforce quote template from opportunity data The business case for accessibility: Five ways it drives enterprise value Python PDF library comparison (2026): 7 libraries for developers Why your AI agent hallucinates PDF table data PDF.js limitations: When to upgrade to a commercial PDF SDK
Kotlin Non-Nullable Pitfall
Michael Kellner · 2023-10-01 · via Inside Nutrient

Table of contents

    Kotlin Non-Nullable Pitfall

    One of the first things you’ll encounter when starting to code with Kotlin is the topic of null safety(opens in a new tab) — especially nullable types and non-null types(opens in a new tab). The Kotlin documentation states the following about non-nullable values:

    “In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that cannot (non-nullable references). For example, a regular variable of type String cannot hold null.”

    The Non-Nullable Null Value

    According to the above, variables of a non-nullable type are never null. But is this really true? In general, yes, but just recently, I stumbled over an exception to this paradigm.

    I worked on a feature that involved text editing on Android — in particular, reacting to changes of the cursor position.

    To achieve that, I derived a new class — CustomEditText — from Android’s AppCompatEditText:

    CustomEditText(context: Context, private val listener: CustomListener): AppCompatEditText(context) {

    override fun onSelectionChanged(selStart: Int, selEnd: Int) {

    super.onSelectionChanged(selStart, selEnd)

    listener.onSelectionChange(selStart, selEnd)

    }

    }

    As you can see, there’s a private non-nullable property, listener, which must be passed in the constructor. We should be good to access this property at any given time.

    But instantiating a CustomEditText causes this error message:

    java.lang.NullPointerException: Attempt to invoke interface method 'super.onSelectionChanged(int, int)' on a null object reference

    Apparently listener was null. What happened?

    The culprit is one of the base class constructors — TextView, to be specific — which calls onSelectionChange() under the hood.

    So here’s a bit more detail: In Kotlin, if you try to access a non-null value in an overridden method during the execution of the base class constructor, you’ll end up with a NullPointerException.

    This is because the base class constructor is executed before the subclass constructor, and if the base class constructor calls an overridden method of the subclass, the constructor of the latter hasn’t even run, yet — and its members are not initialized.

    If possible, avoid calling overridable methods from a constructor.

    In our case, avoiding overridable methods isn’t not an option, because Android’s TextEdit class already calls onSelectionChanged from its constructor.

    So, the obvious way to solve the problem is using Kotlin’s safe-call operator, ?.(opens in a new tab):

    override fun onSelectionChanged(selStart: Int, selEnd: Int) {

    super.onSelectionChanged(selStart, selEnd)

    listener?.onSelectionChange(selStart, selEnd)

    }

    Unfortunately, in my case, this wasn’t enough. Here at PSPDFkit, we have very strict linter rules, which deem this change unacceptable, because “why use a safe-call if the value can never be null?” As a result, the compiler emits an “unnecessary safe-call” compiler error.

    There are two options to address this. The first is to suppress the warning:

    override fun onSelectionChanged(selStart: Int, selEnd: Int) {

    super.onSelectionChanged(selStart, selEnd)

    @Suppress("UNNECESSARY_SAFE_CALL")

    listener?.onSelectionChange(selStart, selEnd)

    }

    The second is to introduce a function that takes a nullable parameter and hence works around the linter rule:

    override fun onSelectionChanged(selStart: Int, selEnd: Int) {

    super.onSelectionChanged(selStart, selEnd)

    handleOnSelectionChange(selStart, selEnd)

    }

    private fun handleOnSelectionChange(selStart: Int, selEnd: Int) {

    listener?.onSelectionChange(selStart, selEnd)

    }

    I chose the second option, because I tend to avoid @Supress commands. However, which option you choose doesn’t make much of a difference; it’s simply a matter of preference.

    Conclusion

    Generally it can be said non-nullable types behave as expected, with the exception of when constructors call an overridable method. To be safe, be sure to check base class constructors.

    Explore related topics

    Try for free Ready to get started?

    Related SDK articles

    Explore more