Java에서의 함수 포인터
이것은 평범하고 사소한 것일 수도 있지만, 저는 구체적인 답을 찾는 데 어려움을 겪고 있는 것 같습니다.C#에는 위임의 개념이 있으며, 이는 C++로부터의 함수 포인터의 개념과 강하게 관련되어 있습니다.자바에도 비슷한 기능이 있나요?포인터가 다소 결여되어 있는 것을 고려하면, 이것에 대한 가장 좋은 방법은 무엇일까요?확실히 하자면 우린 일등석이야
함수 포인터와 같은 기능을 위한 Java 관용구는 인터페이스를 구현하는 어나니머스 클래스입니다.
Collections.sort(list, new Comparator<MyClass>(){
public int compare(MyClass a, MyClass b)
{
// compare objects
}
});
업데이트: Java 8 이전 버전에서는 위의 내용이 필요합니다.이제 우리는 람다와 같은 훨씬 더 좋은 대안을 가지고 있다.
list.sort((a, b) -> a.isGreaterThan(b));
및 메서드 참조:
list.sort(MyClass::isGreaterThan);
함수 포인터를 인터페이스로 대체할 수 있습니다.컬렉션을 실행하고 각 요소에 대해 작업을 수행한다고 가정합니다.
public interface IFunction {
public void execute(Object o);
}
이것은 CollectionUtils 2.doFunc(Collection c, IFunction f)라고 하는 사람에게 전달할 수 있는 인터페이스입니다.
public static void doFunc(Collection c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
예를 들어, 숫자 모음이 있고 각 요소에 1을 더하려고 합니다.
CollectionUtils2.doFunc(List numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
}
});
반사를 사용해서 할 수 있어요.
개체와 메서드 이름(문자열)을 매개 변수로 전달하고 메서드를 호출합니다.예를 들어 다음과 같습니다.
Object methodCaller(Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
// Catch the exceptions
}
다음으로 다음과 같이 사용합니다.
String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");
물론 모든 예외를 확인하고 필요한 깁스를 추가합니다.
아니요, 함수는 Java에서 퍼스트 클래스 객체가 아닙니다.핸들러 클래스를 실장하는 것으로, 같은 작업을 실시할 수 있습니다.이것은 Swing 등에서의 콜백의 실장 방법입니다.
그러나 향후 Java 버전에는 폐쇄에 대한 제안(당신이 말하는 것에 대한 공식 이름)이 있습니다.Javawolld는 흥미로운 기사를 가지고 있습니다.
이것은 스티브 예게의 명사왕국 처형을 떠올리게 한다.기본적으로 Java는 모든 동작을 위한 오브젝트를 필요로 하므로 함수 포인터와 같은 "동사 전용" 엔티티를 가지고 있지 않습니다.
유사한 기능을 사용하려면 익명 내부 클래스를 사용할 수 있습니다.
를 Foo
.21; 묶음21.21; 묶음
interface Foo {
Object myFunc(Object arg);
}
를 .bar
이치노
public void bar(Foo foo) {
// .....
Object object = foo.myFunc(argValue);
// .....
}
마지막으로 다음과 같이 메서드를 호출합니다.
bar(new Foo() {
public Object myFunc(Object arg) {
// Function code.
}
}
Java8은 람다와 메서드 참조를 도입했습니다.따라서 기능이 기능 인터페이스와 일치하는 경우(자신의 인터페이스를 작성할 수 있습니다) 이 경우 메서드레퍼런스를 사용할 수 있습니다.
Java는 일련의 공통 기능 인터페이스를 제공합니다.다음 작업을 수행할 수 있습니다.
public class Test {
public void test1(Integer i) {}
public void test2(Integer i) {}
public void consumer(Consumer<Integer> a) {
a.accept(10);
}
public void provideConsumer() {
consumer(this::test1); // method reference
consumer(x -> test2(x)); // lambda
}
}
자바에는 그런 게 없어요.오브젝트에 대한 메서드에 대한 참조를 전달하려면 함수를 어떤 오브젝트로 정리하고 참조를 해당 오브젝트에 전달해야 합니다.
구문론적으로, 이것은 인플레이스(in-place)로 정의된 익명 클래스 또는 클래스의 멤버 변수로 정의된 익명 클래스를 사용하면 어느 정도 완화될 수 있습니다.
예:
class MyComponent extends JPanel {
private JButton button;
public MyComponent() {
button = new JButton("click me");
button.addActionListener(buttonAction);
add(button);
}
private ActionListener buttonAction = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// handle the event...
// note how the handler instance can access
// members of the surrounding class
button.setText("you clicked me");
}
}
}
리플렉션을 사용하여 Java에서 콜백/위임 지원을 구현했습니다.자세한 내용과 작업 소스는 제 웹사이트에서 확인할 수 있습니다.
구조
Callback이라는 이름의 기본 클래스와 WithParms라는 이름의 중첩 클래스가 있습니다.콜백을 필요로 하는 API는 Callback 객체를 파라미터로 하여 필요에 따라 Callback을 작성합니다.메서드 변수로서의 WithParms.이 오브젝트의 어플리케이션의 대부분은 재귀적이기 때문에 매우 깔끔하게 동작합니다.
퍼포먼스가 여전히 높은 우선 순위이기 때문에 기동할 때마다 파라미터를 유지하는 일회용 객체 어레이를 만들고 싶지 않았습니다.결국 대규모 데이터 구조에서는 수천 개의 요소가 존재할 수 있으며 메시지 처리 시나리오에서는 초당 수천 개의 데이터 구조를 처리할 수 있습니다.
스레드 세이프를 실현하기 위해서는 API 메서드의 각 호출에 대해 파라미터 배열이 고유하게 존재해야 하며 효율성을 위해 콜백의 호출마다 동일한 파라미터를 사용해야 합니다.콜백을 호출용 파라미터 배열로 바인드하기 위해 작성하는 비용이 저렴한 두 번째 오브젝트가 필요했습니다.단, 경우에 따라서는 다른 이유로 호출자에 파라미터 배열이 이미 있을 수 있습니다.이러한 두 가지 이유로 파라미터 배열은 Callback 객체에 속하지 않았습니다.또한 호출 선택(파라미터를 배열 또는 개별 개체로 전달)은 내부 작업에 가장 적합한 호출을 사용할 수 있도록 콜백을 사용하여 API의 손에 있습니다.
WithParms 네스트클래스는 옵션이며 2가지 목적에 대응합니다.콜백 호출에 필요한 파라미터 오브젝트 배열이 포함되어 있으며 파라미터 배열을 로드한 후 콜백타깃을 호출하는 10개의 오버로드 invoke() 메서드(1~10개의 파라미터 포함)를 제공합니다.
폐쇄가 람다지 라이브러리에서 어떻게 구현되었는지 확인합니다.실제로는 C#의 위임자와 매우 유사한 동작을 합니다.
http://code.google.com/p/lambdaj/wiki/Closures
여기 있는 대부분의 사람들에 비해 나는 자바에 익숙하지 않지만 비슷한 제안을 본 적이 없기 때문에 다른 대안이 있다.그게 좋은 방법인지 아닌지, 심지어 전에 제안했는데도 이해가 안 돼요.저는 그냥 자기 묘사가 잘 된 것 같아서 좋아요.
/*Just to merge functions in a common name*/
public class CustomFunction{
public CustomFunction(){}
}
/*Actual functions*/
public class Function1 extends CustomFunction{
public Function1(){}
public void execute(){...something here...}
}
public class Function2 extends CustomFunction{
public Function2(){}
public void execute(){...something here...}
}
.....
/*in Main class*/
CustomFunction functionpointer = null;
응용 프로그램에 따라 할당
functionpointer = new Function1();
functionpointer = new Function2();
기타.
들르다
functionpointer.execute();
언급URL : https://stackoverflow.com/questions/1073358/function-pointers-in-java
'programing' 카테고리의 다른 글
C 콜백 함수로서의 C++ 클래스멤버 함수 사용 (0) | 2022.06.05 |
---|---|
Vue2: 경고:프롭을 직접 뮤트하지 않음 (0) | 2022.06.05 |
스토어에서 Vue 플러그인을 사용하는 방법 (0) | 2022.06.05 |
크기 뒤에 괄호를 사용해야 하는 이유와 시기 (0) | 2022.06.05 |
범용 타입 T의 클래스인스턴스를 가져오려면 어떻게 해야 하나요? (0) | 2022.06.05 |