জাভাতে স্থির পদ্ধতি থেকে কীভাবে getClass () কল করবেন?


350

আমার একটি ক্লাস রয়েছে যা অবশ্যই কিছু স্থির পদ্ধতিতে থাকতে পারে। এই স্থিতিশীল পদ্ধতির ভিতরে আমাকে নীচের কল করার জন্য পদ্ধতি getClass () কল করতে হবে:

public static void startMusic() {
  URL songPath = getClass().getClassLoader().getResource("background.midi");
}

তবে গ্রহন আমাকে বলে:

Cannot make a static reference to the non-static method getClass() 
from the type Object

এই সংকলন সময়ের ত্রুটি ঠিক করার উপযুক্ত উপায় কী?


ব্যবহার getResource()করার আগে সেখানে একটি ব্যবহারকারী সংজ্ঞায়িত একটি দৃষ্টান্ত (যেমন অ এ J2SE) বর্গ কখনও কখনও ব্যর্থ হবে। সমস্যাটি হ'ল জেআরই সেই পর্যায়ে বুটস্ট্র্যাপ ক্লাস-লোডার ব্যবহার করবে, যার ক্লাস-পাথে (বুটস্ট্র্যাপ লোডারটির) অ্যাপ্লিকেশন সংস্থান থাকবে না।
অ্যান্ড্রু থম্পসন

উত্তর:


616

উত্তর

শুধু TheClassName.classপরিবর্তে ব্যবহার করুন getClass()

লগারদের ঘোষণা

যেহেতু এটি একটি নির্দিষ্ট ইউজকেসটির জন্য এত বেশি মনোযোগ পেয়েছে - লগ ডিক্লেয়ারেশন sertোকানোর একটি সহজ উপায় সরবরাহ করার জন্য - আমি ভেবেছিলাম যে আমি এতে আমার চিন্তাভাবনা যুক্ত করব। লগ ফ্রেমওয়ার্কগুলি প্রায়শই লগটিকে একটি নির্দিষ্ট প্রসঙ্গে সীমাবদ্ধ রাখার প্রত্যাশা করে, একটি সম্পূর্ণ-দক্ষ শ্রেণীর নাম বলে। সুতরাং এগুলি সংশোধন ছাড়াই অনুলিপিযোগ্য নয়। পেস্ট-নিরাপদ লগ ঘোষণার জন্য পরামর্শগুলি অন্যান্য জবাবগুলিতে সরবরাহ করা হয়, তবে তাদের বাইসকোডে স্ফীত করা বা রানটাইম অন্তর্নির্ধারণের মতো ডাউনসাইড রয়েছে। আমি এগুলি সুপারিশ করি না। অনুলিপি-পেস্ট একটি সম্পাদক উদ্বেগ, সুতরাং একটি সম্পাদক সমাধান সবচেয়ে উপযুক্ত।

ইন্টেলিজিতে, আমি একটি লাইভ টেম্পলেট যুক্ত করার পরামর্শ দিই:

  • সংক্ষেপে "লগ" ব্যবহার করুন
  • private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class);টেম্পলেট পাঠ্য হিসাবে ব্যবহার করুন ।
  • পরিবর্তনগুলি সম্পাদনা ক্লিক করুন এবং অভিব্যক্তিটি ব্যবহার করে CLASS যুক্ত করুন className()
  • পুনরায় ফর্ম্যাট করতে এবং এফকিউ নামগুলি সংক্ষিপ্ত করতে বাক্সগুলি চেক করুন।
  • জাভা: ঘোষণা প্রসঙ্গে পরিবর্তন করুন।

এখন আপনি যদি log<tab>এটি টাইপ করেন তবে এটি স্বয়ংক্রিয়ভাবে প্রসারিত হবে

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

এবং স্বয়ংক্রিয়ভাবে আপনার জন্য আমদানি পুনরায় ফর্ম্যাট করুন optim


6
যখন ভুল কোডটি অন্য কোনও শ্রেণিতে চলছে তখন এটি অনুলিপি / পেস্ট এবং দুঃখজনক দুঃখের ফলাফলের ফলস্বরূপ।
উইলিয়াম এন্টারিকেন

1
@ উইলিয়ামএন্ট্রিকেন: বেনামে অভ্যন্তরীণ ক্লাস ব্যবহার করা এটির পক্ষে দুর্দান্ত সমাধান নয়, এটি কয়েক বেকার বিকাশকারী প্রচেষ্টা বাঁচানোর জন্য অতিরিক্ত ক্লাসফাইলে আপনার বাইকোডকে স্ফীত করে। আমি নিশ্চিত নই যে লোকেরা যেখানে করছেন সেখানে তারা সমস্ত জায়গাতেই অনুলিপি / পেস্ট করতে হবে তবে এটি ভাষা হ্যাক নয়, একটি সম্পাদক সমাধান দিয়ে চিকিত্সা করা উচিত। উদাহরণস্বরূপ, যদি ইন্টেলিজ ব্যবহার করে, একটি লাইভ টেম্পলেট ব্যবহার করুন যা শ্রেণীর নামটি সন্নিবেশ করতে পারে।
মার্ক পিটার্স

1
আমি সত্যিই অবাক হয়েছি কেন আপনি 4 টি
ডাউনটি

"আমি নিশ্চিত নই যে লোকেরা যেখানে সমস্ত জায়গাতেই অনুলিপি / পেস্ট করতে হবে সেখানে কী করছে" - Logঅ্যান্ড্রয়েডে ব্যবহার করার মতো কিছু , যার জন্য একটি ট্যাগ সরবরাহ করা প্রয়োজন, সাধারণত শ্রেণীর নাম। এবং সম্ভবত অন্যান্য উদাহরণ আছে। অবশ্যই আপনি এটির জন্য একটি ক্ষেত্র ঘোষণা করতে পারেন (যা সাধারণ অনুশীলন) তবে এটি এখনও অনুলিপি এবং পেস্ট করুন।
ব্যবহারকারীর 149408

1
আপনি আপনার লাইভ টেম্পলেট সমাধানটিতে একটি জিনিস ভুলে গেছেন: "পরিবর্তনগুলি সম্পাদনা করুন" এবং CLASSটাইপ করার জন্য এক্সপ্রেশনটিতে ক্লিক করুন className()। এটি নিশ্চিত করবে যে $ CLASS actually আসলে শ্রেণীর নামের সাথে প্রতিস্থাপিত হয়েছে, অন্যথায় এটি খালি বাইরে আসবে।
হার্বসিএসও

122

প্রশ্নের কোড উদাহরণ হিসাবে, স্ট্যান্ডার্ড সমাধানটি ক্লাসটির নাম দ্বারা স্পষ্টভাবে উল্লেখ করা এবং getClassLoader()কল ছাড়াই এটি করাও সম্ভব :

class MyClass {
  public static void startMusic() {
    URL songPath = MyClass.class.getResource("background.midi");
  }
}

এই পদ্ধতির এখনও পিছনের দিক রয়েছে যে আপনি যদি এই কোডটিকে একই সাথে অনেকগুলি ক্লাসে অনুলিপি করতে চান তবে এটি অনুলিপি / পেস্ট ত্রুটিগুলির বিরুদ্ধে খুব নিরাপদ নয়।

এবং শিরোনামে সঠিক প্রশ্নের হিসাবে, সংলগ্ন থ্রেডে পোস্ট করা একটি কৌশল রয়েছে :

Class currentClass = new Object() { }.getClass().getEnclosingClass();

এটি Objectকার্যকর করা প্রসঙ্গটি ধরে রাখতে নেস্টেড বেনামে সাবক্লাস ব্যবহার করে। এই কৌশলটি অনুলিপি / নিরাপদ পেস্ট হওয়ার সুবিধা রয়েছে ...

এটি অন্যান্য ক্লাসের উত্তরাধিকার সূত্রে একটি বেস ক্লাসে ব্যবহার করার সময় সাবধানতা:

এটিও লক্ষণীয় যে এই স্নিপেটটি যদি তখন কিছু বেস শ্রেণীর স্থিতিশীল পদ্ধতি হিসাবে তৈরি হয় currentClass মানটি সর্বদা সেই বেস শ্রেণীর জন্য একটি রেফারেন্স হয়ে থাকে যা কোনও পদ্ধতিতে যে সাবক্লাস ব্যবহার করে may


23
এখন পর্যন্ত আমার প্রিয় উত্তর। NameOfClass.class সুস্পষ্ট, তবে এর জন্য আপনাকে নিজের শ্রেণীর নাম জানতে হবে। GetEnclosingClass কৌশলটি কেবল অনুলিপি ব্যবহারের জন্য অনুলিপি ব্যবহারের জন্য স্থির বেস শ্রেণির পদ্ধতিগুলির জন্যও কার্যকর নয়
ডোমিংগো

1
ঘটনাচক্রে Class.getResource()থেকে কিছুটা আলাদা আচরণ করতে পারে ClassLoader.getResource(); দেখতে stackoverflow.com/a/676273
augurar

68

জাভা 7 + এ আপনি স্থির পদ্ধতি / ক্ষেত্রগুলিতে এটি করতে পারেন:

MethodHandles.lookup().lookupClass()

আপনার যদি কেবল প্রধান পদ্ধতি থেকে সহায়তা মুদ্রণের জন্য getSimpleName () কল প্রয়োজন হয় তবে খুব ভাল সমাধান ।
দিমিত্রি বুলাশেভিচ

6
আমি প্রতিবার ক্লাসের নাম পরিবর্তন না করে যেখানেই লগার যুক্ত করার জন্য একটি 'অনুলিপি পেস্ট' সমাধান সন্ধান করছিলাম। আপনি এটি আমাকে দিয়েছিলেন: private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
জুলিয়ান ফেনিউ

যেখানে এটি সমর্থিত সর্বোত্তম সমাধান, অপূর্ণতা হ'ল এন্ড্রয়েড
এআইপিআই

24

আমি নিজেই এই নিয়ে কুস্তি করেছিলাম। স্থির প্রসঙ্গে থাকাকালীন ক্লাসলডার পেতে বর্তমান থ্রেডটি ব্যবহার করা একটি দুর্দান্ত কৌশল। এটি হ্যাডোপ ম্যাপ্রেডুসে পাশাপাশি কাজ করবে। স্থানীয় পদ্ধতিতে চলার সময় অন্যান্য পদ্ধতিগুলি কাজ করে, তবে যখন কোনও মানচিত্রে ব্যবহৃত হয় তখন নাল ইনপুটস্ট্রিমটি ফেরত দেয়।

public static InputStream getResource(String resource) throws Exception {
   ClassLoader cl = Thread.currentThread().getContextClassLoader();
   InputStream is = cl.getResourceAsStream(resource);
   return is;
}


11

getClass() পদ্ধতিটি নিম্নলিখিত স্বাক্ষর সহ অবজেক্ট শ্রেণিতে সংজ্ঞায়িত করা হয়েছে:

পাবলিক ফাইনাল ক্লাস getClass ()

যেহেতু এটি হিসাবে সংজ্ঞায়িত করা হয়নি static, আপনি এটি কোনও স্ট্যাটিক কোড ব্লকের মধ্যে কল করতে পারবেন না। আরও তথ্যের জন্য এই উত্তরগুলি দেখুন: Q1 , Q2 , Q3

আপনি যদি কোনও স্থির প্রসঙ্গে থাকেন তবে ক্লাসটি পেতে আপনাকে ক্লাসের আক্ষরিক ভাবটি ব্যবহার করতে হবে, সুতরাং আপনাকে মূলত এগুলি করতে হবে:

Foo.class

এই ধরণের অভিব্যক্তিকে ক্লাস লিটারালস বলা হয় এবং সেগুলি জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন বইয়ে ব্যাখ্যা করা হয়েছে:

ক্লাস আক্ষরিক এমন একটি অভিব্যক্তি যা একটি শ্রেণীর নাম, ইন্টারফেস, অ্যারে বা আদিম ধরণের নামের সাথে followed এর পরে থাকে by ' এবং টোকেন বর্গ। ক্লাস আক্ষরিকের ধরণ হল ক্লাস। এটি বর্তমান উদাহরণের শ্রেণীর সংজ্ঞায়িত শ্রেণি লোডার দ্বারা নির্ধারিত হিসাবে বর্ণিত (বা শূন্যতার জন্য) শ্রেণীর অবজেক্টের মূল্যায়ন করে।

আপনি ক্লাসের জন্য এপিআই ডকুমেন্টেশনে এই বিষয় সম্পর্কে তথ্যও পেতে পারেন ।


9

চেষ্টা করে দেখুন

Thread.currentThread().getStackTrace()[1].getClassName()

অথবা

Thread.currentThread().getStackTrace()[2].getClassName()

এই পদ্ধতির সৌন্দর্য হ'ল এটি 8 (API 26) এর আগে অ্যান্ড্রয়েড সংস্করণগুলিতেও কাজ করবে। সাবধান থাকুন যে সূচকটি [1]সমস্ত লগ বার্তাগুলিকে Threadঅ্যান্ড্রয়েড 4.4.4 এ তাদের উত্স হিসাবে রিপোর্ট করবে । [2]অ্যান্ড্রয়েড এবং ওপেনজেআরই উভয় ক্ষেত্রেই সঠিক ফলাফল বলে মনে হচ্ছে।
ব্যবহারকারীর 149408

0

মনে করুন কোনও ইউটিলিটি শ্রেণি রয়েছে, তবে নমুনা কোডটি হবে -

    URL url = Utility.class.getClassLoader().getResource("customLocation/".concat("abc.txt"));

কাস্টম লোকেশন - যদি উত্সগুলির মধ্যে কোনও ফোল্ডার কাঠামো অন্যথায় এই স্ট্রিংটিকে আক্ষরিক অপসারণ করে।


-2

এরকম কিছু চেষ্টা করুন। এটা আমার জন্য কাজ করে. লগ (শ্রেণীর নাম)

    String level= "";

    Properties prop = new Properties();

    InputStream in =
            Logg.class.getResourceAsStream("resources\\config");

    if (in != null) {
        prop.load(in);
    } else {
        throw new FileNotFoundException("property file '" + in + "' not found in the classpath");
    }

    level = prop.getProperty("Level");

1
নিশ্চিত নন কেন তুমি একই উত্তর এই থ্রেড ইতিমধ্যই থাকা যে তিনবার প্রদানের করছেন যারা 2013 থেকে 2011 থেকে দুবার, একবার
Antares42

ক্লাস লোডার দ্বারা "রিসোর্সগুলি \\ কনফিগারেশন" ফোল্ডারে অ্যাক্সেস সহ শ্রেণি লগড লোড করা থাকলে এই সমাধানটি কাজ করে। কিছু সার্ভারে যাদের একাধিক ক্লাসলোডার রয়েছে (উদাহরণস্বরূপ একটি শ্রেণীবদ্ধকারী lib ফোল্ডার লোড করতে এবং অন্যান্য অ্যাপ্লিকেশন এবং সংস্থানগুলি লোড করতে অন্য), এটি সত্য নয়। যে কারণে, এই উত্তরটির সমাধান পিউপোজ কেবল কখনও কখনও কাকতালীয়ভাবে কাজ করে!
ম্যানুয়েল রোমেরো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.