2017-01-04 11 views
10

Предположим, что нам нужно реализовать некоторый java-метод в собственном коде и выставить его пользователю. Мы знаем, что вся работа выполняется на родной стороне, т. Е. Единственная ответственность java-кода - передать предоставленные пользователем аргументы в собственный код и вернуть результат обратно. В соответствии с этим, ява слой может быть реализован двумя способами:Собственные методы Java. Public vs. private

  • При использовании нативных методов, которые непосредственно подвергаются пользователю:

    public native Object doSmth(Object arg0, Object arg1); 
    
  • С помощью тонкой общественной обертки вокруг частного нативного метода :

    public Object doSmth(Object arg0, Object arg1) { 
        return nativeDoSmth(arg0, arg1); 
    } 
    
    private native Object nativeDoSmth(Object arg0, Object arg1); 
    

Я видел оба подхода в реальных проектах и ​​даже как бывший и последний в том же проекте.

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

+5

«Открытый» метод является частью API объектов. Метод «native» - это решение для реализации. Детали реализации не должны быть видны публичному API. Вариант 2 скрывает реализацию от API. – Andreas

+1

Вы найдете вариант 2, используемый исключительно в JDK, а не в варианте 1. Я думаю, что это хорошая идея, это дает вам еще одну степень свободы при разработке и поддержании вашего уровня JNI. – EJP

+0

Ваш вопрос предполагает, что подписи совпадают. Это часто бывает не так, потому что естественным для API класса может быть много работы в коде JNI. Во многих случаях проще преобразовывать входы и выходы с использованием Java в типы данных, с которыми легче работать в JNI. –

ответ

3

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

Достоинством полезности является ключ здесь. Как указано в комментариях, объект раскрывает свое поведение. Как это реализовано, это не бизнес пользователя. Это дает вам большую гибкость.

Предположим, что в будущем (см.: ремонтопригодность) вы обнаружите, что вам нужно/нужно настроить метод таким образом, чтобы он что-то делал до и/или после обычного вызова. В первом подходе вам нужно будет отказаться от метода и создать новый. Во втором втором подходе вы просто добавляете все, что вам нужно в методе, и пользователю все равно.

Что касается производительности, теоретически, первый подход быстрее, потому что это 1 вызов меньше. На практике это совершенно незначительно.

+0

Нет необходимости оспаривать метод, так как вы можете просто перейти от первого варианта ко второму, не обращая внимания на какой-либо код клиента. Поэтому нет необходимости использовать второй, прежде чем это действительно понадобится. Конечно, это потребует перекомпиляции собственного кода, но это должно быть под вашим контролем. – Holger

+0

@ Хольджер я не понимаю. В первом подходе вы хотите внести изменения в собственный код? Те же изменения, которые вы сделали бы на стороне Java, если бы вы использовали второй подход? – user1803551

+0

Нет. Когда необходимо украсить метод со стороны Java, вы можете просто изменить вариант 1 на вариант 2, получив все преимущества второго варианта. Так как имя «родной» метод отличается в обоих вариантах, необходимо изменить имя собственного кода или создать делегат с созданным новым именем. В любом случае нативный код нужно будет перекомпилировать, но существенно не изменить. – Holger

2

Я думаю, что это в основном индивидуальный стиль. Если вы считаете, следующий код:

rattias-MacBookPro: TST rattias $ Diff Test1.cl Test1.class rattias-MacBookPro: TST rattias $ VI Test1.java

public class Test1 { 
    public static void main(String[] args) { 
    Test2 t = new Test2(); 
    t.m(); 
    } 
} 

public class Test2 { 
    public native void m(); 
} 

Компиляция это производит Test1.class который идентичен тот, образующиеся при Test2 определяются следующим образом:

public class Test2 { 
    public void m() { 
    } 
} 

Это означает, что вы могли бы изменить реализацию, чтобы быть родным, чистый Java, чистый Java оберткой для родного частного метода, в любой момент времени, не затрагивая пользователей. Может возникнуть вопрос о том, должна ли общая функция публичного API быть родной, а не только частью вычисления, но опять же, которую можно изменить в любой момент.