java 在字符串中截取方法名

java 在字符串中截取方法名,第1张

import javautilHashMap;

import javautilMap;

import javautilregexMatcher;

import javautilregexPattern;

public class ParseString {

private static final String PARAM_KEY = "!";

public static void main(String[] args) throws Exception {

// 待解析字符串

String method = "methodName(methodName2(methodName4(2,3,4),2),methodName3(),strName)";

// 这句很重要,先删除字符串中所有的空格,后面的正则中不再需要考虑空字符问题

method = methodreplaceAll("\\s+", "");

// 输出结果

for (MapEntry<String, Integer> entry : parseMethod(method)entrySet()) {

Systemoutprintln(entrygetKey() + " --- " + entrygetValue());

}

}

private static Map<String, Integer> parseMethod(String method) {

Map<String, Integer> ret = new HashMap<>();

Pattern p = Patterncompile("^([^\\(]+)\\(()\\)$");

Matcher m = pmatcher(method);

if (!mfind())

throw new RuntimeException("错误的方法字符串:" + method);

// 找到方法

Map<String, Integer> paramMap = parseParams(mgroup(2));

retput(mgroup(1)trim(), paramMapremove(PARAM_KEY));

retputAll(paramMap);

return ret;

}

private static Map<String, Integer> parseParams(String params) {

Map<String, Integer> ret = new HashMap<>();

int count = 0;

while(paramslength() > 0) {

if (paramssplit(",")[0]indexOf("(") >= 0) {

// 第一个参数为方法

String method = findFirstMethod(params);

params = (methodlength() == paramslength())  "" : paramssubstring(methodlength() + 1);

retputAll(parseMethod(method));

} else {

// 第一个参数为非方法

params = paramsreplaceAll("[^,]+(,(+))", "$2");

}

count++;

}

retput(PARAM_KEY, count);

return ret;

}

private static String findFirstMethod(String params) {

String method = "";

boolean start = false;

int matchCount = 0;

for (int i = 0; i < paramslength(); i++) {

char ch = paramscharAt(i);

if (ch == '(') {

start = true;

matchCount++;

} else if (ch == ')') {

matchCount--;

}

method += paramssubstring(i, i + 1);

if (start && matchCount == 0) break;

}

if (start)

return method;

throw new RuntimeException("错误的参数字符串:" + params);

}

}

可以使用以下代码来获取src目录下所有的包名,类名,方法名 以及通过一个类名获得该类下的所有方法名。

import javaioFile;

import javalangreflectMethod;

public class LoopApp {

public static void main(String[] args) throws Exception {

String packageName = "";

File root = new File(SystemgetProperty("userdir") + "\\src");

loop(root, packageName);

}

public static void loop(File folder, String packageName) throws Exception {

File[] files = folderlistFiles();

for (int fileIndex = 0; fileIndex < fileslength; fileIndex++) {

File file = files[fileIndex];

if (fileisDirectory()) {

loop(file, packageName + filegetName() + "");

} else {

listMethodNames(filegetName(), packageName);

}

}

}

public static void listMethodNames(String filename, String packageName) {

try {

String name = filenamesubstring(0, filenamelength() - 5);

Object obj = ClassforName(packageName + name);

Method[] methods = objgetClass()getDeclaredMethods();

Systemoutprintln(filename);

for (int i = 0; i < methodslength; i++) {

Systemoutprintln("\t" + methods[i]getName());

}

} catch (Exception e) {

Systemoutprintln("exception = " + egetLocalizedMessage());

}

}

}

可以使用js的eval函数实现,示例如下:

<script type="text/javascript">

//自定义函数,用于d出三个参数的值

function alertFunc(str1,str2,str3){

alert(str1);

alert(str2);

alert(str3);

}

//自定义函数:根据传入的函数名,调用函数

function callAlert(functionName){

//根据函数名得到函数类型

var func=eval(functionName);

//创建函数对象,并调用

new func(arguments[1],arguments[2],arguments[3]);

}

</script>

<!--编写按钮,在点击事件中调用函数-->

<button onclick="callAlert('alertFunc','tom','hello','world')" >测试函数调用</button>

如何通过接口的DispID 获取方法名?

最近研究了Delphi RTTI

想要实现一个类似TAutoObject功能的类

经过以下试验分析

Delphi 的双重接口的调用模式大致如下

Delphi(Pascal) code //接口

ITest = interface(IDispatch)

['{C8E5E6FF-FBF2-4397-A4F3-8041DF9548E8}']

function Test: Boolean; stdcall;

end;

{$m-}{$METHODINFO OFF}

//disp接口

ITestDisp = dispinterface

['{C8E5E6FF-FBF2-4397-A4F3-8041DF9548E8}']

function Test: Boolean; dispid 500;

end;

TTest = class(TInterfacedObject, ITest, IDispatch)

protected

function Test: Boolean; stdcall;

function GetTypeInfoCount(out Count: Integer): HResult; stdcall;

function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;

function GetIDsOfNames(const IID: TGUID; Names: Pointer;

NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;

function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;

Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;

end;

//以下是调用

var

I: ITest;

Disp: ITestDisp;

V: Variant;

begin

//用非disp接口调用, 直接执行到 Test 方法内部

I := TTestCreate;

ITest;

//用dips接口调用,执行到Invoke,再由 Invoke 执行其它方法

Disp := TTestCreate as ITestDisp;

DispTest;

//用Variant调用,首先执行到 GetIDsOfNames 获取方法ID,然后再执行到 Invoke 再由 Invoke 执行其它方法

V := TTestCreate as ITestDisp;

VTest;

end;

我想要的效果正是类似DispID的效果, 既只要有接口就可以调用, 避免传错参数或调错方法,

然而我发现当执行到 Invoke 时传来的只是方法的DispID

于是我无从下手了,不知道该如何把DispID解释成方法名或方法地址,于是无法进行调用实际想调用的方法

跟据我的实验,用Variant的方式,只要在其调用GetIDsOfNames时生成一个模拟的DispID,

这个DispID便可以由Invoke获取了,然而这个DispID却不是接口声明时的DispID,于是

用disp接口仍然无法获取方法地址

我跟踪过TAutoObject的调用,他的调用是通过工厂类直接执行,然而一直跟踪下去才发现他是调用了Ole32 API,而这个API

是需要IDL Table支持的,即一定要是COM或COM+才能获取到。

用Variant调用的方式确实能满足我的需要,但其不能直接使用接口调用,传错参数也能编译通过,并且效比较低,

首先要执行 GetIDsOfNames获取方法ID,再进行调用。

经过跟踪调试发现,只要引用了ComObj单元,Disp接口调用时,都会调用到ComObj的DispCallByIDProc函数指针,该指针指向

DispCallByID 函数,通过修改这个函数的指针,指向自己的DispCallByID,由DispCallByID转向Invoke以外的另一个方法把

方法名传过去,也能达到我想要的效果,但是这样做是修改了Delphi内部的调用机制,比起

这种方法,我更倾向于使用原有的机制,如果通过通过DispID获取到方法地址那才是最佳解决案。

一、从注解中获取

使用注解方式,我们需要自定义一个注解,在注解中指定参数名,然后通过反射机制,获取方法参数上的注解,从而获取到相应的注解信息。这里自定义的注解是Param,通过value参数指定参数名,定义了一个工具类ParameterNameUtils来获取指定方法的参数名列表,这里获取测试类ParameterNameTest中定义的方法method1的参数名列表表,下面是具体的代码。

以上就是关于java 在字符串中截取方法名全部的内容,包括:java 在字符串中截取方法名、java怎么获取src目录下所有的包名,类名,方法名 以及通过一个类名获得该类下的所有方法名、如何通过一个js方法的方法名,获取到这个js方法定义的代码(方法体)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10179076.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-06
下一篇2023-05-06

发表评论

登录后才能评论

评论列表(0条)

    保存