ক্লাসের নাম ব্যবহার করে একটি কনস্ট্যান্ট তৈরি করা এবং কনস্ট্রাক্টর কল করা


312

শ্রেণীর নাম (গতিশীল) দেওয়া এবং তার নির্মাণকারীর কাছে প্যারামিটারগুলি দেওয়ার জন্য কোনও নির্দিষ্ট শ্রেণীর উদাহরণ তৈরি করার কোনও উপায় আছে কি?

কিছুটা এইরকম:

Object object = createInstance("mypackage.MyClass","MyAttributeValue");

যেখানে "MyAttributeValue"নির্মাণকারীর পক্ষে একটি যুক্তি MyClass

উত্তর:


497

হ্যাঁ, এরকম কিছু:

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });

এটি অবশ্যই একক স্ট্রিং প্যারামিটারের জন্য কাজ করবে তবে আপনি এটি খুব সহজেই সংশোধন করতে পারবেন।

নোট করুন যে শ্রেণীর নামটি একটি পুরোপুরি যোগ্যতাসম্পন্ন হতে হবে, অর্থাত্ নেমস্পেস সহ। নেস্টেড ক্লাসগুলির জন্য, আপনাকে একটি ডলার ব্যবহার করতে হবে (সংকলকটি এটি ব্যবহার করে)। উদাহরণ স্বরূপ:

package foo;

public class Outer
{
    public static class Nested {}
}

এর জন্য Classঅবজেক্টটি পেতে, আপনার প্রয়োজন হবে Class.forName("foo.Outer$Nested")


5
newInstance()এটি একটি ভার্সেস পদ্ধতি (ঠিক যেমন GetConstructor()), সুস্পষ্ট- Objectঅ্যারে তৈরির প্রয়োজন নেই ।
জোয়াকিম সাউর

18
@ জোয়াচিম: আমি জানি এটি ভারার্গস, তবে আপনার Object[]যুক্তি থাকলে এটি জটিল হয়ে উঠতে পারে, আমি এ ক্ষেত্রে সুস্পষ্টভাবে অ্যারে তৈরি করতে পছন্দ করি।
জন স্কিটি

2
clazz.getConstructor (String.class); এখানে স্ট্রিং.ক্লাস কেন?
উমায়ের এ।

2
@ নিউট্রালাইজার: হ্যাঁ, তবে আমি এমন প্রশ্নের উত্তর দিয়েছিলাম যেখানে এটির গতিশীল হওয়ার দরকার নেই।
জন স্কেটি

3
@ জোনস্কিট আমি বুঝতে পেরেছি আপনি কোথা থেকে এসেছেন, তবে এটি এতটা সহজ নয় - আমি ডক্সটি দেখেছি কিন্তু বিভ্রান্ত হয়েছিলাম, তবে এটিও যদি আমি পরীক্ষা করে দেখেছিলাম এবং এটি কাজ করে - ঠিক আছে তবে এটি কাজ করেছে - তবে যদি এটি কাজ না করে তবে সমস্যাটি কিছুটা কনফিগারেশনের অভাবে বা আমার পক্ষ থেকে কিছু থাকায় আমি নিশ্চিত হতে পারতাম - প্রায়শই এই জাতীয় প্রশ্ন জিজ্ঞাসা করার সময় লোকেরা দরকারী টিডবাইটি দেয় যা সত্যই সহায়তা করে। এই কারণেই একটি সহজ "হ্যাঁ এটি কাজ করবে - যদি আপনি এটি এভাবে করেন" বা "কোনও উপায় নেই" সত্যই সহায়তা করে। তবে এখন আমার বোঝার উপায় নেই যে
ycomp

97

আপনি পছন্দসই শ্রেণীর Class.forName()একটি Classজিনিস পেতে ব্যবহার করতে পারেন ।

তারপরে ব্যবহার করুন getConstructor() কাঙ্ক্ষিত Constructorবস্তুটি সন্ধান করতে ।

শেষ অবধি, newInstance()আপনার নতুন উদাহরণটি পেতে সেই বস্তুকে কল করুন।

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");

81

আপনি প্রতিচ্ছবি ব্যবহার করতে পারেন

return Class.forName(className).getConstructor(String.class).newInstance(arg);

3
যদি ডিফল্ট কনস্ট্রাক্টর ব্যবহার করে থাকেন তবে স্ট্রিংক্লাস প্যারামিটার মানটি মুছে ফেলুন যেমন Class.forName (ClassName) .getConstructor ()। NewInstance (arg);
বিজয় কুমার

21
@ বিজয়কুমার আমার মনে হয় আপনার অর্থ বোঝানো হয়েছে Class.forName(className).getConstructor().newInstance();;)
পিটার লরে

14

শ্রেণিতে যদি কেবল একটি ফাঁকা নির্মাতা থাকে (যেমন ক্রিয়াকলাপ বা ফ্রেগমেন্ট ইত্যাদি, অ্যান্ড্রয়েড ক্লাস):

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];

2
এটিই আমাকে সাহায্য করেছিল। Constructor<?> ctor = clazz.getConstructor(String.class)আমার জন্য কাজ করে বলে মনে হচ্ছে না।
লিও সি হান

8

(যেমন) ব্যবহার getConstructor(String.lang)করার সময় কনস্ট্রাক্টরটিকে সর্বজনীন ঘোষণা করতে হবে। অন্যথায় একটি NoSuchMethodExceptionনিক্ষেপ করা হয়।

আপনি যদি কোনও জন-সরকারী নির্মাতাকে অ্যাক্সেস করতে চান তবে আপনাকে তার পরিবর্তে (যেমন) ব্যবহার করতে হবে getDeclaredConstructor(String.lang)



4

Class<?>কনস্ট্রাক্টর আর্গুমেন্ট (পাস) দিয়ে পাসওয়ার্ড ব্যবহার করে জাভাতে কোনও অবজেক্ট তৈরি করার খুব সহজ উপায় :

কেস 1: - এখানে এই Mainশ্রেণীর একটি ছোট কোড :

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Main {

    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        // Get class name as string.
        String myClassName = Base.class.getName();
        // Create class of type Base.
        Class<?> myClass = Class.forName(myClassName);
        // Create constructor call with argument types.
        Constructor<?> ctr = myClass.getConstructor(String.class);
        // Finally create object of type Base and pass data to constructor.
        String arg1 = "My User Data";
        Object object = ctr.newInstance(new Object[] { arg1 });
        // Type-cast and access the data from class Base.
        Base base = (Base)object;
        System.out.println(base.data);
    }

}

এবং, এখানে Baseশ্রেণিবদ্ধ:

public class Base {

    public String data = null;

    public Base() 
    {
        data = "default";
        System.out.println("Base()");
    }

    public Base(String arg1) {
        data = arg1;
        System.out.println("Base("+arg1+")");
    }

}

কেস 2: - আপনি একাধিক যুক্তি এবং অনুলিপি কনস্ট্রাক্টর সহ কনস্ট্রাক্টরের জন্য একইভাবে কোড করতে পারেন। উদাহরণস্বরূপ, 3 টি আর্গুমেন্ট Baseকনস্ট্রাক্টর হিসাবে প্যারামিটার হিসাবে পাস করার জন্য ক্লাসে কনস্ট্রাক্টর তৈরি করতে হবে এবং উপরে কোড পরিবর্তন করতে হবে:

Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" }); 

এবং এখানে বেস শ্রেণিটি একরকম দেখতে হবে:

public class Base {

    public Base(String a, String b, String c){
        // This constructor need to be created in this case.
    }   
}

দ্রষ্টব্য: - কোডটিতে হ্যান্ডেল করা দরকার এমন বিভিন্ন ব্যতিক্রমগুলি পরিচালনা করতে ভুলবেন না।


আর একটি উপায় বিদ্যমান জাভা অবজেক্টটি ক্লোন করেও করা হয়। এটি বিদ্যমান জাভা সামগ্রীর একটি অনুলিপি তৈরি করে। এই ক্ষেত্রে, আপনাকে ডিপ অনুলিপি বা শ্যালো কপি ধারণাটিও পরিচালনা করতে হবে।
রাহুল রায়না

2

যদি কেউ সিঙ্গলটন প্যাটার্নটি অনুসরণ করে শ্রেণি সত্ত্বেও কোনও শ্রেণীর উদাহরণ তৈরি করার উপায় খুঁজছেন, তা করার একটি উপায় এখানে।

// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");

// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();

// Since it is private, make it accessible.
cons.setAccessible(true);

// Create new object. 
Object obj = cons.newInstance();

এটি কেবল এমন ক্লাসগুলির জন্যই কাজ করে যা একটি প্রাইভেট কনস্ট্রাক্টর ব্যবহার করে সিঙ্গলটন প্যাটার্ন প্রয়োগ করে।


1

আপনি তৈরি বস্তুর ভিতরে পদ্ধতিগুলিও আহ্বান করতে পারেন।

আপনি প্রথম কনট্রাক্টরকে অনুরোধ করে অবজেক্ট তাত্ক্ষণিক তৈরি করতে পারেন এবং তারপরে তৈরি বস্তুটিতে প্রথম পদ্ধতিটি শুরু করতে পারেন।

    Class<?> c = Class.forName("mypackage.MyClass");
    Constructor<?> ctor = c.getConstructors()[0];
    Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
    c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);

আপনি কীভাবে জানবেন যে খুব প্রথম নির্মাণকারী Stringপ্যারামিটার হিসাবে নেয় ? আপনি যখন কনস্ট্রাক্টর অর্ডার পরিবর্তন করেন তখন কিছুটা অগোছালো হয়ে যায়
ফরিদ

ক্লাস ডকুমেন্টেশন থেকে @ ফরিদ
হাতেম

তবুও getConstructor(ClassName.class)ভাল, আমার ধারণা। এমনকি যদি নির্মাণকারীদের ক্রম শ্রেণিতে পরিবর্তিত হয় তবে ম্যানুয়ালি পজিশনটি খুঁজে পাওয়ার দরকার নেই
ফরিদ

@ ফরিড - সি.জেটড্যাক্লেয়ারড ম্যাথোডস () [0] .আনভোক (অবজেক্ট, অবজেক্ট ... মেথডআরগস); আপনার প্রয়োজন হতে পারে কিছু ক্ষেত্রে বিশেষ নির্মাতা নির্দিষ্ট করে; তবে আপনি ঠিক বলেছেন।
হাতেম বদাভি

1

আর একটি সহায়ক উত্তর। আমি কীভাবে getConstructor (প্যারামস) ব্যবহার করব? নতুন ইনস্ট্যান্স (আরগস)?

return Class.forName(**complete classname**)
    .getConstructor(**here pass parameters passed in constructor**)
    .newInstance(**here pass arguments**);

আমার ক্ষেত্রে, আমার শ্রেণীর নির্মাতা ওয়েবড্রাইভারকে প্যারামিটার হিসাবে নেয়, তাই কোডের নীচে ব্যবহার করা হয়:

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.