可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there a way to bind parameters parameters to function pointers in Java like you can with std::bind in C++? What would the Java equivalent of something like this be?
void PrintStringInt(const char * s, int n)
{
std::cout << s << ", " << n << std::endl;
}
void PrintStringString(const char * s, const char * s2)
{
std::cout << s << ", " << s2 << std::endl;
}
int main()
{
std::vector<std::function<void(const char *)>> funcs;
funcs.push_back(std::bind(&PrintStringInt, std::placeholders::_1, 4));
funcs.push_back(std::bind(&PrintStringString, std::placeholders::_1, "bar"));
for(auto i = funcs.begin(); i != funcs.end(); ++i){
(*i)("foo");
}
return 0;
}
回答1:
This is as close as I think you can get to a line by line translation, bind
does not map 1:1 to any Java construct;
static void PrintStringInt(String s, int n)
{
System.out.println(s + ", " + n);
}
static void PrintStringString(String s, String s2)
{
System.out.println(s + ", " + s2);
}
interface MyCall {
void fn(String value);
}
public static void main(String[] argv)
{
Vector<MyCall> funcs = new Vector<MyCall>();
funcs.add(new MyCall() {
@Override public void fn(String value) {PrintStringInt(value, 4); }});
funcs.add(new MyCall() {
@Override public void fn(String value) {PrintStringString(value, "bar"); }});
for(MyCall i : funcs){
i.fn("foo");
}
}
回答2:
I'm afraid not, but this code is an approach to mimic the C++ templates (poorly):
abstract class Printer<T> {
final T value;
Printer( T v ) {
value = v;
}
public abstract void print( String s );
}
class PrintStringInt extends Printer< Integer> {
PrintStringInt( int v ) {
super( v );
}
@Override public void print( String s ) {
System.out.printf( "%s, %d\n", s, value );
}
}
class PrintStringString extends Printer< String > {
PrintStringString( String v ) {
super( v );
}
@Override public void print( String s ) {
System.out.printf( "%s, %s\n", s, value );
}
}
public class BindTest {
public static void main( String[] args ) {
Printer<?>[] funcs = {
new PrintStringInt( 4 ),
new PrintStringString( "bar")
};
for( Printer<?> p : funcs ) {
p.print( "foo" );
}
}
}
Outputs:
foo, 4
foo, bar
回答3:
From Java7 on, one could do the same also with method handles, see the API doc of class java.lang.invoke.MethodHandle
for details.
回答4:
Use MethodHandle, here is an example
public class HW
{
int sum;
public HW(int a, int b)
{
super();
this.sum = a+b;
}
public void hello1(double c)
{
double newnumber = sum+c;
System.out.println("hello from hello1, new number= " + newnumber);
}
public void hello2()
{
System.out.println("hello from hello2, sum=" + sum);
}
}
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class TestMethodHandle
{
/**
* @param args
*/
public static void main(String[] args)
{
HW hw = new HW(10, 15);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh;
try
{
mh = lookup.findVirtual(HW.class, "hello2",
MethodType.methodType(void.class));
mh.invoke(hw);
mh = lookup.findVirtual(HW.class, "hello1",
MethodType.methodType(void.class, double.class));
mh.invoke(hw, 20);
} catch (NoSuchMethodException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
} catch (Throwable e)
{
e.printStackTrace();
}
}
回答5:
You can create an anonymous class with a function of the desired signature, that forwards calls to the original function.
Let's say you have these functions:
public class StringPrinter {
public void printStringInt( String s, int n ) {
System.out.println( s + ", " + n );
}
public void printStringString( String s, String s2 ) {
System.out.println( s + ", " + s2 );
}
}
Then you can create anonymous classes that effectively bind arguments to these functions.
public static void main( String[] args ) {
public interface Print1String {
public void printString( String s );
}
List<Print1String> funcs = new ArrayList<Print1String);
funcs.add( new Print1String() {
public void printString( String s ) {
new StringPrinter( ).printStringInt( s, 42 );
}});
funcs.add( new Print1String() {
public void printString( String s ) {
new StringPrinter( ).printStringString( s, "bar" );
}});
for ( Print1String func : funcs ) {
func.print1String("foo");
}
}