Приведение и проверка типов — Kotlin

Операторы is и !is

Используйте оператор is или его отрицание !is, чтобы проверить соответствует ли объект заданному типу во время исполнения.

if (obj is String) {
    print(obj.length)
}
if (obj !is String) { // то же самое, что и !(obj is String)
    print("Not a String")
}
else {
    print(obj.length)
}

Умные приведения

В большинстве случаев вам не нужно использовать явные приведения в Kotlin, потому что компилятор отслеживает is-проверки и явные преобразования для неизменяемых значений и вставляет (безопасно) приведения автоматически, там, где они нужны.

fun demo(x: Any) {
    if (x is String) {
        print(x.length) // x автоматически преобразовывается в String
    }
}

Компилятор достаточно умён для того, чтобы понимать, что приведения безопасны в случаях, когда проверка на несоответствие типу (!is) приводит к выходу из функции:

if (x !is String) return
print(x. length) // x автоматически преобразовывается в String

или в случаях, когда приводимая переменная находится справа от оператора && или ||, а соответствующая проверка (обычная или отрицательная) находится слева:

// x автоматически преобразовывается в String справа от `||`
if (x !is String || x.length == 0) return
// x автоматически преобразовывается в String справа от `&&`
if (x is String && x.length > 0) {
    print(x.length) // x автоматически преобразовывается в String
}

Умные приведения работают вместе с when-выражениями и циклами while:

when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}

Заметьте, что умные приведения работают только тогда, когда компилятор может гарантировать, что переменная не изменится между проверкой и использованием. Точнее говоря, умные приведения будут работать:

  • с локальными val переменными — всегда за исключением локальных делегированных свойств. ;
  • с val свойствами — если поле имеет модификатор доступа private или internal, или проверка происходит в том же модуле, в котором объявлено это свойство. Умные приведения неприменимы к публичным свойствам или свойствам, которые имеют переопределённые getter’ы;
  • с локальными var переменными — если переменная не изменяется между проверкой и использованием, не захватывается лямбдой, которая её модифицирует и не является локальным делегированным свойством;
  • с var свойствами — никогда, потому что переменная может быть изменена в любое время другим кодом.

Оператор «небезопасного» приведения

Обычно оператор приведения выбрасывает исключение, если приведение невозможно, поэтому мы называем его небезопасным. Небезопасное приведение в Kotlin выполняется с помощью инфиксного оператора as:

val x: String = y as String

Заметьте, что null не может быть приведен к String, так как String не является nullable, т. е. если y — null, код выше выбросит исключение. Чтобы сделать этот код корректным для null-значений, используйте nullable-тип в правой части приведения.

val x: String? = y as String?

Оператор «безопасного» (nullable) приведения

Чтобы избежать исключения, вы можете использовать оператор безопасного приведения as?, который возвращает null в случае неудачи.

val x: String? = y as? String

Заметьте, что несмотря на то, что справа от

as? стоит non-null тип String, результат приведения является nullable.

Стирание и проверка типов у Обобщений (Generics)

Котлин обеспечивает типобезопасность операций, связанных с обобщениями на этапе компиляции, в то время как информация о типе аргумента обобщения недоступна во время выполнения программы. Например, для List<Foo> происходит стирание типа, что превращает его в List<*>. В связи с чем, нет способа проверить, принадлежит ли объект конкретному типу во время выполнения программы.

Учитывая это, компилятор запрещает is

-проверки, которые не могут быть выполнены во время выполнения программы из-за стирания типов, например ints is List<Int> или list is T (параметризированный тип). Однако у вас есть возможность произвести проверку со «звёздными» проекциями.

if (something is List<*>) {
    something.forEach { println(it) } // Элементы типа `Any?`
}

Таким же образом, когда у вас есть статически определенный тип аргумента, вы можете произвести is-проверку или приведение с необобщенной частью типа. Заметьте, что в данном случае угловые скобки пропущены:

fun handleStrings(list: List<String>) {
    if (list is ArrayList) {
        // `list` приводится к `ArrayList<String>` путём "умного приведения"
    }
}

Аналогичный синтаксис, но с пропущенным типом аргумента может использоваться для приведений, которые не принимают типы аргументы: list as ArrayList.

Встроенные (inline) функции с параметрами вещественного типа имеют свои аргументы типа, встроенные на каждый момент вызова, что позволяет arg is T проверять параметризованный тип, но если arg является объектом обобщенного типа, его аргумент типа по-прежнему стираются.

inline fun <reified A, reified B> Pair<*, *>.asPairOf(): Pair<A, B>? {
    if (first !is A || second !is B) return null
    return first as A to second as B
}
val somePair: Pair<Any?, Any?> = "items" to listOf(1, 2, 3)
val stringToSomething = somePair.asPairOf<String, Any>()
val stringToInt = somePair.asPairOf<String, Int>()
val stringToList = somePair.asPairOf<String, List<*>>()
val stringToStringList = somePair.asPairOf<String, List<String>>() // Нарушает типобезопасность!
fun main() {
    println("stringToSomething = " + stringToSomething)
    println("stringToInt = " + stringToInt)
    println("stringToList = " + stringToList)
    println("stringToStringList = " + stringToStringList)
    //println(stringToStringList?.
second?.forEach() {it.length}) // Это вызовет исключение ClassCastException, так как элементы списка не являются строками }

Непроверяемые (Unchecked) приведения

Как упоминалось выше, стирание типов делает невозможным проверку типа аргумента обобщения на этапе выполнения, и обобщенные типы в коде могут быть недостаточно связаны друг с другом, чтобы компилятор обеспечил типобезопасность.

Тем не менее иногда мы имеем программную логику высокого уровня, которая подразумевает типобезопасность.

fun readDictionary(file: File): Map<String, *> = file.inputStream().use {
    TODO("Прочитать сопоставление строк с произвольными элементами.")
}
// Мы сохранили словарь (map) `Int`ов в файл
val intsFile = File("ints.dictionary")
// Warning: Unchecked cast: `Map<String, *>` to `Map<String, Int>`
val intsDictionary: Map<String, Int> = readDictionary(intsFile) as Map<String, Int>

Компилятор выдает предупреждение для приведения в последней строке. Приведение не может быть полностью проверено во время выполнения и нет дает гарантии, что значения в словаре (map) являются Int.

Чтобы избежать непроверяемые приведения, вы можете изменить структуру программы: в примере выше возможно объявить интерфейсы

DictionaryReader<T> и DictionaryWriter<T> с типобезопасными имплементациями для различных типов. Правильное использование вариативности обобщений также может помочь.

Для обобщенных функций, используемых встроенные (inline) функции с параметрами вещественного типа приведение типа arg as T является проверяемым, до тех пор, пока тип arg не имеет свои аргументы типа, которые были стерты.

Предупреждение о непроверяемом приведении можно убрать используя аннотации @Suppress("UNCHECKED_CAST").

inline fun <reified T> List<*>.asListOfType(): List<T>? =
    if (all { it is T })
        @Suppress("UNCHECKED_CAST")
        this as List<T> else
        null

В JVM, массивы (Array<Foo>) сохраняют информацию о стираемом типе их элементов, и приведение типов к массиву частично проверяется: nullability и фактические аргументы для параметризированных элементов массива все еще стираются. Например, приведение foo as Array <List <String>?> будет успешным, если foo является массивом List <*>, независимо от того, является ли он nullable или нет.

Преобразование строки в целое число в Groovy

Наш мир глазами ИИ, пример. Источник: ArchDaily

1. Обзор​

В этом кратком руководстве мы покажем различные способы преобразования из строки в целое число в Groovy.

2. Кастинг с

as

Первый метод, который мы можем использовать для преобразования, — это ключевое слово as , которое аналогично вызову метода asType() класса « :

@Test
void givenString_whenUsingAsInteger_thenConvertToInteger() {
def stringNum = "123"
Integer expectedInteger = 123
Integer integerNum = stringNum as Integer

assertEquals(integerNum, expectedInteger)
}

Как и выше, мы можем использовать int :

@Test
void givenString_whenUsingAsInt_thenConvertToInt() {
def stringNum = "123"
int expectedInt = 123
int intNum = stringNum as int

assertEquals(intNum, expectedInt)
}

3.

целое число

Другой метод — из расширения Groovy JDK для java.lang.CharSequence :

@Test
void givenString_whenUsingToInteger_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
int intNum = stringNum.toInteger()

assertEquals(intNum, expectedInt)
}

4.

Целое#parseInt

Третий способ — использовать статический метод Java Integer.parseInt() :

@Test
void givenString_whenUsingParseInt_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
int intNum = Integer.parseInt(stringNum)

assertEquals(intNum, expectedInt)
}

5.

Целое#intValue

Альтернативный метод — создать новый объект Integer и вызвать его метод intValue :

@Test
void givenString_whenUsingIntValue_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
int intNum = new Integer(stringNum). intValue()

assertEquals(intNum, expectedInt)
}

Или, в этом случае, мы также можем использовать просто new Integer(stringNum) :

@Test
void givenString_whenUsingNewInteger_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
int intNum = new Integer(stringNum)

assertEquals(intNum, expectedInt)
}

6.

Целое число#valueOf

Подобно Integer.parseInt() , мы также можем использовать статический метод Java Integer#valueOf :

@Test
void givenString_whenUsingValueOf_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
int intNum = Integer.valueOf(stringNum)

assertEquals(intNum, expectedInt)
}

7.

Десятичный формат

И для нашего последнего метода мы можем применить класс DecimalFormat Java :

@Test
void givenString_whenUsingDecimalFormat_thenConvertToInteger() {
def stringNum = "123"
int expectedInt = 123
DecimalFormat decimalFormat = new DecimalFormat("#")
int intNum = decimalFormat. parse(stringNum).intValue()

assertEquals(intNum, expectedInt)
}

8. Обработка исключений​

Таким образом, если преобразование не удается, например, если есть нечисловые символы, будет выдано исключение NumberFormatException . Кроме того, в случае, когда String имеет значение null , будет выброшено исключение NullPointerException :

@Test(expected = NumberFormatException.class)
void givenInvalidString_whenUsingAs_thenThrowNumberFormatException() {
def invalidString = "123a"
invalidString as Integer
}

@Test(expected = NullPointerException.class)
void givenNullString_whenUsingToInteger_thenThrowNullPointerException() {
def invalidString = null
invalidString.toInteger()
}

Чтобы этого не произошло, мы можем использовать метод isInteger :

@Test
void givenString_whenUsingIsInteger_thenCheckIfCorrectValue() {
def invalidString = "123a"
def validString = "123"
def invalidNum = invalidString?. isInteger() ? invalidString as Integer : false
def correctNum = validString?.isInteger() ? validString as Integer : false

assertEquals(false, invalidNum)
assertEquals(123, correctNum)
}

9. Резюме​

В этой короткой статье мы показали несколько эффективных способов переключения с объектов String на объекты Integer в Groovy.

Когда дело доходит до выбора наилучшего метода преобразования типа объекта, все вышеперечисленное одинаково хорошо. Самое главное — избежать ошибок, сначала проверив, может ли значение String в нашем приложении быть нечисловым, пустым или нулевым .

Как обычно, все примеры кода можно найти на GitHub .

Scala: Как преобразовать String в Int (Integer)

Часто задаваемые вопросы по Scala: Как преобразовать String в Int в Scala?

Решение: используйте toInt

Если вам нужно преобразовать String в Int в Scala, используйте метод toInt , который доступен для объектов String , например:

scala>  val i = "1". toInt 
я: Целое = 1
 

Как видите, я просто привел строку "1" в объект Int с использованием метода toInt , который доступен для любой строки .

Однако имейте в виду, что это может привести к ошибке NumberFormatException , как это происходит в Java:

scala>  val i = "foo".toInt 
java.lang.NumberFormatException: для входной строки: "foo"
 

, поэтому вы захотите учесть это в своем коде, например, с оператором Scala try / catch .

Java-подобная функция преобразования строки в целое число

Следующие функции показывают несколько способов обработки исключений, которые могут быть выброшены в процессе преобразования строки в целое число. В этом первом примере показан способ «Java» для записи функции преобразования String в Int :

def toInt(s: String): Int = {
  пытаться {
    s. toInt
  } ловить {
    случай e: Исключение => 0
  }
}
 

Эта функция возвращает правильное значение типа int, если строка может быть преобразована в тип int (например, «42»), и возвращает 0, если строка является чем-то другим, например строкой «foo».

Когда я говорю, что эта функция использует подход, подобный Java, обратите внимание, что изначально я написал эту статью до того, как в Java появился тип Optional .

Функция преобразования Scala «String to Int», использующая параметр

Более «подобный Scala» способ записи функции преобразования строки в int выглядит следующим образом:

def toInt(s: String): Option[Int] = {
  пытаться {
    Некоторые (s.toInt)
  } ловить {
    случай e: Исключение => Нет
  }
}
 

Эта функция возвращает Some(Int) , если строка успешно преобразована в целое число, и None , если строку не удалось преобразовать в целое число. Эта функция показана в следующих примерах REPL:

scala>  val x = toInt("foo") 
х: Опция[Int] = Нет

scala>  val x = toInt("10") 
х: Опция [Int] = Некоторые (10)
 

Как я писал в своей книге о Scala и функциональном программировании, вы также можете написать Scala toInt функция, использующая Try , Success и Failure , например:

импортировать scala.util. {Попытка, успех, неудача}
def makeInt(s: String): Try[Int] = Try(s.trim.toInt)
 

Вы также можете вернуть Option следующим образом:

импортировать scala.util.control.Exception._
def makeInt(s: String): Option[Int] = allCatch.opt(s.toInt)
 

См. мой учебник по идиомам Scala Option/Some/None, чтобы узнать больше о способах использования этих шаблонов и о том, как использовать Вариант и Попробуйте результаты .

этот пост спонсирован моими книгами:

#1 Новый релиз

FP Бестселлер

Изучите Скала 3

Быстро выучить FP

Примечание. Как я уже упоминал выше, метод toInt на самом деле не относится к классу String. На самом деле он содержится в классе с именем StringOps, который связан с классом String с помощью неявного преобразования в Scala. Я описываю это немного подробнее в статье Как показать методы String и StringOps в примерах Scala REPL.

Kotlin — преобразование строки в целое число

Преобразование строки в целое число в Kotlin

Чтобы преобразовать строку в целое число в Kotlin, используйте метод String.toInt() или Integer.parseInt(). Если строку можно преобразовать в допустимое целое число, любой из методов возвращает значение int.

Вам может понадобиться преобразовать строку в целое число в таких сценариях, как: извлечение чисел из строковых сообщений и выполнение над ними некоторых арифметических операций; вы получаете значение в виде строки извне вашей программы, но вы обрабатываете его как целое число в своем приложении; и т. д.

В этом уроке мы изучим различные способы преобразования строки в целое число и различные сценарии, в которых нам может понадобиться использовать это преобразование.

Синтаксис

Синтаксис String.toInt() приведен ниже.

 String.toInt() 

String.toInt() возвращает значение int, если преобразование прошло успешно. В противном случае создается исключение java.lang.NumberFormatException.

Синтаксис Integer.parseInt() приведен ниже.

 Целое число.parseInt(String) 

Функция Integer.parseInt() принимает строку в качестве аргумента и возвращает значение int, если преобразование прошло успешно. В противном случае выдается такое же исключение java.lang.NumberFormatException, как и в случае String.toInt().

Примеры

1. Преобразовать строку в целое с помощью String.toInt()

В этом примере мы сначала инициализируем строку. Во-вторых, мы вызываем toInt() для строки и сохраняем возвращенное значение int. Вы можете использовать это значение int в соответствии с вашими требованиями, но в этом примере мы просто печатаем его.

пример.kt

 /**
 * Kotlin — преобразование Sting в Integer
 */
весело main(аргументы: Array) {
    //строка
    ул ул = "241"
    // преобразовать строку в целое число
    числовое значение = str.toInt()
    печать (число + 10)
} 

Запустите эту программу Kotlin. Просто чтобы доказать, что это целое число, мы добавляем к нему значение 10 и печатаем результат.

Вывод

 251 

2. Преобразование строки в целое число с помощью Integer.parseInt()

В этом примере мы сначала инициализируем строку. Во-вторых, мы вызываем Integer.parseInt() со строкой в ​​качестве аргумента строки и сохраняем возвращенное значение int.

пример.kt

 /**
 * Kotlin — преобразование Sting в Integer
 */
весело main(аргументы: Array) {
    //строка
    ул ул = "241"
    // преобразовать строку в целое число
    val число = Integer.parseInt (строка)
    печать (число + 10)
} 

Запустите эту программу Kotlin. Как и в предыдущем примере, мы добавляем значение 10 к целому числу и печатаем результат.

Выходные данные

 251 

3. Преобразование строки в целое — отрицательный сценарий

В этом примере мы попробуем преобразовать строку в целое число, где строка в целом не представляет допустимое целое число. Давайте посмотрим, что происходит. Конечно, str.toInt() выдает исключение.

пример.kt

 /**
 * Kotlin — преобразование Sting в Integer
 */
весело main(аргументы: Array) {
    //строка
    ул ул = "241а"
    // преобразовать строку в целое число
    числовое значение = str.toInt()
    печать (число + 10)
} 

Запустите эту программу Kotlin, и вы получите следующий вывод.

Вывод

 Исключение в потоке "main" java.lang.NumberFormatException: Для входной строки: "241a"
в java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.