আমার যদি এর মতো ক্লাস থাকে:
public class Whatever
{
public void aMethod(int aParam);
}
এটির কোনও উপায় আছে যা aMethod
নামের সাথে একটি প্যারামিটার ব্যবহার করে aParam
, এটি টাইপ int
?
আমার যদি এর মতো ক্লাস থাকে:
public class Whatever
{
public void aMethod(int aParam);
}
এটির কোনও উপায় আছে যা aMethod
নামের সাথে একটি প্যারামিটার ব্যবহার করে aParam
, এটি টাইপ int
?
উত্তর:
সংক্ষেপ:
method.getParameterTypes()
সম্পাদকের জন্য স্বতঃসিদ্ধ কার্যকারিতা লেখার স্বার্থে (আপনি যে কোনও একটি মন্তব্যে বলেছেন) এখানে কয়েকটি বিকল্প রয়েছে:
arg0
, arg1
, arg2
ইত্যাদিintParam
, stringParam
, objectTypeParam
, ইত্যাদিজাভা 8 এ আপনি নিম্নলিখিতগুলি করতে পারেন:
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
public final class Methods {
public static List<String> getParameterNames(Method method) {
Parameter[] parameters = method.getParameters();
List<String> parameterNames = new ArrayList<>();
for (Parameter parameter : parameters) {
if(!parameter.isNamePresent()) {
throw new IllegalArgumentException("Parameter names are not present!");
}
String parameterName = parameter.getName();
parameterNames.add(parameterName);
}
return parameterNames;
}
private Methods(){}
}
সুতরাং আপনার শ্রেণীর জন্য Whatever
আমরা একটি ম্যানুয়াল পরীক্ষা করতে পারি:
import java.lang.reflect.Method;
public class ManualTest {
public static void main(String[] args) {
Method[] declaredMethods = Whatever.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
if (declaredMethod.getName().equals("aMethod")) {
System.out.println(Methods.getParameterNames(declaredMethod));
break;
}
}
}
}
[aParam]
আপনি যদি -parameters
আপনার জাভা 8 সংকলকের কাছে তর্কটি পাস করেন তবে মুদ্রণ করা উচিত ।
ম্যাভেন ব্যবহারকারীদের জন্য:
<properties>
<!-- PLUGIN VERSIONS -->
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<!-- OTHER PROPERTIES -->
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<!-- Original answer -->
<compilerArgument>-parameters</compilerArgument>
<!-- Or, if you use the plugin version >= 3.6.2 -->
<parameters>true</parameters>
<testCompilerArgument>-parameters</testCompilerArgument>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
আরও তথ্যের জন্য নিম্নলিখিত লিঙ্কগুলি দেখুন:
প্যারানামার লাইব্রেরিটি একই সমস্যাটি সমাধানের জন্য তৈরি করা হয়েছিল।
এটি কয়েকটি ভিন্ন উপায়ে পদ্ধতির নাম নির্ধারণ করার চেষ্টা করে। যদি ক্লাসটি ডিবাগিংয়ের সাথে সংকলিত হয় তবে এটি শ্রেণীর বাইকোড পড়ে তথ্যগুলি বের করতে পারে।
আরেকটি উপায় হ'ল এটি একটি সঙ্কলিত হওয়ার পরে শ্রেণীর বাইকোডে একটি প্রাইভেট স্ট্যাটিক সদস্যকে ইনজেক্ট করা, তবে এটি একটি জারে রাখার আগে। এটি রানটাইমে ক্লাস থেকে এই তথ্যটি বের করার জন্য প্রতিবিম্ব ব্যবহার করে।
https://github.com/paul-hammant/paranamer
এই লাইব্রেরিটি ব্যবহার করতে আমার সমস্যা হয়েছিল তবে শেষ পর্যন্ত এটি কাজ করে ফেললাম। আমি সমস্যাগুলি রক্ষণাবেক্ষণকারীকে রিপোর্ট করার আশা করছি।
ParameterNAmesNotFoundException
org.springframework.core.DefaultParameterNameDiscoverer শ্রেণি দেখুন
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] params = discoverer.getParameterNames(MathUtils.class.getMethod("isPrime", Integer.class));
হ্যাঁ.
কোড জাভা 8 অনুবর্তী কম্পাইলার দিয়ে কম্পাইল করা আবশ্যক ফর্ম্যাল প্যারামিটার নাম (চালু সঞ্চয় করতে বিকল্প -parameters বিকল্প)।
তারপরে এই কোড স্নিপেটে কাজ করা উচিত:
Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
System.err.println(m.getName());
for (Parameter p : m.getParameters()) {
System.err.println(" " + p.getName());
}
}
আপনি প্রতিবিম্ব সহ পদ্ধতিটি পুনরুদ্ধার করতে পারেন এবং এর যুক্তির প্রকারগুলি সনাক্ত করতে পারেন। পরীক্ষা করে দেখুন http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html#getParameterTypes%28%29
তবে আপনি ব্যবহৃত যুক্তির নাম বলতে পারবেন না।
এটি সম্ভব এবং স্প্রিং এমভিসি 3 এটি করে, তবে ঠিক কীভাবে তা দেখতে সময় নি নি।
ইউআরআই টেম্পলেট ভেরিয়েবলের সাথে মেথড প্যারামিটার নামের সাথে মিলে যাওয়া কেবল তখনই করা যেতে পারে যদি আপনার কোডটি ডিবাগিং সক্ষম করে সক্রিয় করা হয়। যদি আপনার ডিবাগিং সক্ষম না করা থাকে তবে একটি প্যারামিটারের সাথে ভেরিয়েবলের সমাধান হওয়া মানকে বাঁধতে আপনার অবশ্যই ইউআরআই টেম্পলেট ভেরিয়েবলের নামটি @PathVariable টীকাতে নির্দিষ্ট করতে হবে। উদাহরণ স্বরূপ:
বসন্তের ডকুমেন্টেশন থেকে নেওয়া
যদিও এটি সম্ভব নয় (যেমন অন্যেরা চিত্রিত করেছেন), আপনি প্যারামিটারের নামটি ধরে রাখার জন্য একটি টীকা ব্যবহার করতে পারেন এবং প্রতিচ্ছবি হলেও তা পেতে পারেন।
সবচেয়ে পরিষ্কার সমাধান নয়, তবে এটি কাজটি সম্পন্ন করে। কিছু ওয়েবসার্ভিস আসলে প্যারামিটারের নাম রাখার জন্য এটি করে (যেমন: গ্লাসফিশের সাথে ডাব্লুএসকে স্থাপন করা)
Java.beans.ConstructorPererties দেখুন , এটি হ'ল এটি করার জন্য ডিজাইন করা।
সুতরাং আপনার করা উচিত:
Whatever.declaredMethods
.find { it.name == 'aMethod' }
.parameters
.collect { "$it.type : $it.name" }
তবে আপনি সম্ভবত এর মতো একটি তালিকা পাবেন:
["int : arg0"]
আমি বিশ্বাস করি এটি গ্রোভির 2.5++ এ স্থির হবে
সুতরাং বর্তমানে, উত্তরটি হ'ল:
আরো দেখুন:
প্রতিটি পদ্ধতির জন্য, তারপর এর মতো কিছু:
Whatever.declaredMethods
.findAll { !it.synthetic }
.collect { method ->
println method
method.name + " -> " + method.parameters.collect { "[$it.type : $it.name]" }.join(';')
}
.each {
println it
}
aMethod
। আমি এটি একটি ক্লাসে সমস্ত পদ্ধতির জন্য পেতে চাই।
antlr
জন্য প্যারামিটারের নাম পেতে পারি না ?
@ বোজহো যেমন বলেছিলেন, সংকলনের সময় ডিবাগের তথ্য অন্তর্ভুক্ত করা থাকলে এটি করা সম্ভব। এখানে একটি ভাল উত্তর আছে ...
কোনও অবজেক্টের কনস্ট্রাক্টরের প্যারামিটারের নামগুলি (প্রতিবিম্ব) কীভাবে পাবেন? @ অ্যাডাম পেয়েন্টার দ্বারা
... এএসএম লাইব্রেরি ব্যবহার করছি। আপনি কীভাবে আপনার লক্ষ্য অর্জন করতে পারবেন তা দেখিয়ে আমি একটি উদাহরণ রেখেছি।
প্রথমত, এই নির্ভরতাগুলির সাথে একটি pom.xML দিয়ে শুরু করুন।
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
তারপরে, এই শ্রেণীর আপনার যা করা উচিত তা করা উচিত। কেবল স্থির পদ্ধতিতে প্রার্থনা করুন getParameterNames()
।
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;
public class ArgumentReflection {
/**
* Returns a list containing one parameter name for each argument accepted
* by the given constructor. If the class was compiled with debugging
* symbols, the parameter names will match those provided in the Java source
* code. Otherwise, a generic "arg" parameter name is generated ("arg0" for
* the first argument, "arg1" for the second...).
*
* This method relies on the constructor's class loader to locate the
* bytecode resource that defined its class.
*
* @param theMethod
* @return
* @throws IOException
*/
public static List<String> getParameterNames(Method theMethod) throws IOException {
Class<?> declaringClass = theMethod.getDeclaringClass();
ClassLoader declaringClassLoader = declaringClass.getClassLoader();
Type declaringType = Type.getType(declaringClass);
String constructorDescriptor = Type.getMethodDescriptor(theMethod);
String url = declaringType.getInternalName() + ".class";
InputStream classFileInputStream = declaringClassLoader.getResourceAsStream(url);
if (classFileInputStream == null) {
throw new IllegalArgumentException(
"The constructor's class loader cannot find the bytecode that defined the constructor's class (URL: "
+ url + ")");
}
ClassNode classNode;
try {
classNode = new ClassNode();
ClassReader classReader = new ClassReader(classFileInputStream);
classReader.accept(classNode, 0);
} finally {
classFileInputStream.close();
}
@SuppressWarnings("unchecked")
List<MethodNode> methods = classNode.methods;
for (MethodNode method : methods) {
if (method.name.equals(theMethod.getName()) && method.desc.equals(constructorDescriptor)) {
Type[] argumentTypes = Type.getArgumentTypes(method.desc);
List<String> parameterNames = new ArrayList<String>(argumentTypes.length);
@SuppressWarnings("unchecked")
List<LocalVariableNode> localVariables = method.localVariables;
for (int i = 1; i <= argumentTypes.length; i++) {
// The first local variable actually represents the "this"
// object if the method is not static!
parameterNames.add(localVariables.get(i).name);
}
return parameterNames;
}
}
return null;
}
}
এখানে ইউনিট পরীক্ষা সহ একটি উদাহরণ।
public class ArgumentReflectionTest {
@Test
public void shouldExtractTheNamesOfTheParameters3() throws NoSuchMethodException, SecurityException, IOException {
List<String> parameterNames = ArgumentReflection
.getParameterNames(Clazz.class.getMethod("callMe", String.class, String.class));
assertEquals("firstName", parameterNames.get(0));
assertEquals("lastName", parameterNames.get(1));
assertEquals(2, parameterNames.size());
}
public static final class Clazz {
public void callMe(String firstName, String lastName) {
}
}
}
আপনি গিটহাবের পুরো উদাহরণটি খুঁজে পেতে পারেন
static
পদ্ধতিগুলির সাথে কাজ করে না । এটি এ ক্ষেত্রে এএসএম দ্বারা ফিরিয়ে দেওয়া যুক্তিগুলির সংখ্যা পৃথক, তবে এটি এমন কিছু যা সহজেই স্থির করা যায়।পরামিতি নামগুলি কেবল সংকলকটির জন্য দরকারী। কম্পাইলার যখন একটি ক্লাস ফাইল তৈরি করে, প্যারামিটারের নামগুলি অন্তর্ভুক্ত করা হয় না - কোনও পদ্ধতির যুক্তির তালিকায় কেবল তার আর্গুমেন্টের সংখ্যা এবং প্রকার থাকে। সুতরাং প্রতিবিম্বটি ব্যবহার করে প্যারামিটারের নামটি পুনরুদ্ধার করা অসম্ভব (আপনার প্রশ্নে ট্যাগ হিসাবে) - এটি কোথাও নেই।
তবে, যদি প্রতিবিম্বের ব্যবহারের কোনও কঠোর প্রয়োজন না হয় তবে আপনি সোর্স কোড থেকে সরাসরি এই তথ্যটি পুনরুদ্ধার করতে পারেন (ধরে নিবেন যে আপনার এটি রয়েছে)।
Parameter names are only useful to the compiler.
ভুল। Retrofit লাইব্রেরি দেখুন। এটি REST এপিআই অনুরোধ তৈরি করতে গতিশীল ইন্টারফেস ব্যবহার করে। এর বৈশিষ্ট্যগুলির মধ্যে একটি হ'ল ইউআরএল পাথগুলিতে স্থানধারকের নামগুলি সংজ্ঞায়িত করা এবং সেই স্থানধারকগুলিকে তাদের সংশ্লিষ্ট প্যারামিটারের নামগুলি প্রতিস্থাপন করার ক্ষমতা।
আমার 2 সেন্ট যোগ করতে; পরামিতি সম্পর্কিত তথ্য "ডিবাগিংয়ের জন্য" ক্লাস ফাইলে পাওয়া যায় যখন আপনি উত্সটি সংকলন করতে জাভ্যাক-জি ব্যবহার করেন। এবং এটি এপিটি-তে উপলব্ধ তবে আপনার একটি টীকা লাগবে যাতে আপনার কোনও ব্যবহার হয় না। (কেউ কেউ এখানে 4-5 বছর আগে অনুরূপ কিছু নিয়ে আলোচনা করেছেন: http://forums.java.net/jive/thread.jspa?messageID=13467&tstart=0 )
সংক্ষেপে সংক্ষেপে আপনি সোর্স ফাইলগুলিতে সরাসরি কাজ না করা (এপিটি সংকলনের সময়ে যা করেন তার অনুরূপ) অবধি আপনি এটি পেতে পারবেন না।