Это вопрос для собеседования:

Предположим, вы пишете код для системы Android, которая использует JNI и некоторый код C ++ для чтения данных из последовательного интерфейса (например, uart).

О вещах нижнего уровня позаботится код C ++, и в конечном итоге данные будут переданы в интерфейс Java, где они будут обрабатываться как тип String.

Возникает вопрос: предположим, что код Java, обрабатывающий чтение, выглядит примерно так:

private void parseSerialData(String input){

 if (input==null){
//DO SOMETHING HERE
    }
}

Будет ли когда-нибудь возможно выполнение условий блока if?

Мое понимание Java подсказывает мне, что это никогда не будет возможным, потому что (я могу полностью ошибиться) null в Java - это способ обозначить «нет ссылки», null не является объектом, и он не был создан из класс. На уровне DVM или JVM, пока переменная была объявлена, ссылка была сделана, даже если для нее в стеке может не быть выделенной памяти.

Следовательно, для локальной переменной в качестве параметра метода невозможно не иметь ссылки для начала, не говоря уже о том, что позже ей была предоставлена ​​ссылка, которая указывает на объект String (даже если этот объект может не иметь с ним никакой информации. , тем не менее, это ненулевой объект), и поэтому условие if никогда не будет выполнено.

Но я не мог решить, является ли этот вопрос вопросом с подвохом, и что-то упустил? Особенно с учетом того, что в драке идет C ++, и я понятия не имею, каково это передать нулевую ссылку C ++ на Java, если это вообще имеет смысл?

Итак, будет ли когда-либо выполнено условие if?

-2
ElasticHeart 9 Мар 2019 в 04:35

1 ответ

Лучший ответ

Да, конечно, input может быть нулевым. Это просто зависит от того, что делает код C ++. Вот полный пример. Из вашего описания не было ясно, возвращает ли собственный метод String или передает его как параметр из собственного метода в метод java, поэтому я включил пример каждого из них.

Эта программа вызывает f пять раз. Первые три раза просто передают постоянное значение. Следующие два раза ждут ввода (в собственном методе) и передают либо null, либо ненулевое значение в f в зависимости от того, является ли ввод пустым или нет.

Test.java

public class Test
{
    static {
        System.loadLibrary("Test");
    }

    public static void main(String [] args)
    {
        Test obj = new Test();
        obj.main();
    }

    void main()
    {
        f(null);
        f("not null");
        String s1 = null;
        f(s1);
        String s2 = n1();
        f(s2);
        n2();
    }

    public void f(String s)
    {
        if (s == null)
            System.out.println("null");
        else
            System.out.println(s);
    }

    native String n1();
    native void n2();
}

Test.cc

#include <stdio.h>
#include <jni.h>
#include "Test.h"

static jstring get_string(JNIEnv *env);

JNIEXPORT jstring JNICALL Java_Test_n1(JNIEnv *env, jobject obj)
{
    return get_string(env);
}

JNIEXPORT void JNICALL Java_Test_n2(JNIEnv *env, jobject obj)
{
    jstring s = get_string(env);
    jclass cls = env->GetObjectClass(obj);
    jmethodID f = env->GetMethodID(cls, "f", "(Ljava/lang/String;)V");
    env->CallVoidMethod(obj, f, s);
}

static jstring get_string(JNIEnv *env)
{
    char buf[20];
    if (fgets(buf, sizeof buf, stdin) == NULL)
        return NULL;
    if (buf[0] == '\n')
        return NULL;
    return env->NewStringUTF(buf);
}

Инструкции по сборке

$ javac Test.java
$ javah Test
$ gcc --std=c++11 -I $JAVA_HOME/include -I $JAVA_HOME/include/linux  -fPIC -shared -o libTest.so Test.cc
$ /usr/bin/java -Djava.library.path=. Test
3
prl 9 Мар 2019 в 08:14