Симон Моурир дал этот пример :
object o = null;
DateTime d = (DateTime)o; // NullReferenceException
, где unboxing преобразование (литье) из object
(или из одного из классов System.ValueType
или System.Enum
или из типа интерфейса) - тип значения (кроме Nullable<>
) сам по себе дает NullReferenceException
.
В другом направлении конверсия бокса из a Nullable<>
, которая имеет HasValue
, равную false
, на ссылочный тип, может дать ссылку null
, которая затем может привести к NullReferenceException
. Классический пример:
DateTime? d = null;
var s = d.ToString(); // OK, no exception (no boxing), returns ""
var t = d.GetType(); // Bang! d is boxed, NullReferenceException
Иногда бокс происходит по-другому. Например, с помощью этого не общего метода расширения:
public static void MyExtension(this object x)
{
x.ToString();
}
следующий код будет проблематичным:
DateTime? d = null;
d.MyExtension(); // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.
Эти случаи возникают из-за специальных правил, используемых во время выполнения при боксе Nullable<>
экземпляров.
Я уверен, что это невозможно сделать с использованием чистой Java - вам, вероятно, придется использовать собственный код для привязки дескриптора файла к объекту FileDescriptor или к объекту FileInputStream или FileOutputStream.
EDIT Если вы используете Linux, * BSD или macOS, вы можете использовать псевдо-файлы / dev / fd / nnn для доступа к файловому дескриптору nnn.
С помощью SUN JavaVM вы можете:
FileDescriptor fd = new FileDescriptor();
sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess().set(fd,3);
FileInputStream fin = new FileInputStream(fd);
Для начала:
Приложения не должны создавать свои собственные дескрипторы файлов
blockquote>Вы можете попробовать использовать отражение для вызова конструктор
private FileDescriptor(int fd)
, получив конструктор и называяsetAccessible(true)
на нем. Но это взломать, и я не могу гарантировать, что это сработает (скорее всего, этого не произойдет). Особенно с цитатой, с которой я начал.
Мне недавно понадобилось сделать это для дочернего процесса Java, работающего в тюрьме. Это означало, что у него не было доступа к файловой системе / dev / fd.
@Bozho сделал комментарий, что отражение может или не может работать для создания объекта FileDescriptor. Однако, похоже, он работает в простом тесте. Ниже приведен источник для TestFD.java:
import java.lang.reflect.Constructor;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
public class TestFD {
public static void main(String[] args) throws Exception {
Constructor<FileDescriptor> ctor = FileDescriptor.class.getDeclaredConstructor(Integer.TYPE);
ctor.setAccessible(true);
FileDescriptor fd = ctor.newInstance(3);
ctor.setAccessible(false);
new FileOutputStream(fd).write("hi there\n".getBytes());
}
}
Чтобы проверить это, я создал простой скрипт Bash, который его компилирует, устанавливает fd3 и запускает java-программу:
#!/bin/bash
javac TestFD.java
exec 3>&1 # open fd3, redirect to stdout
java TestFD
exec 3>&-
Конечно, fd3 перенаправляется на stdout и выводит «hi there there\n» на терминал. Прокомментируйте строку «exec 3> & amp; 1», и программа Java завершится неудачно, как ожидалось, с «IOException», не настроенным на устройство.
Отражение в частном конструкторе FileDescriptor, похоже, отлично работает в тех случаях, когда доступ к / dev / fd невозможно, и он менее суровый, чем попытка создания FileDescriptor с использованием JNI, предложение, которое я видел в другом месте.
Примечание. Я тестировал это в системе BSD. Он может работать или не работать в других системах.