জাভাতে ডাউনকাস্টিং


178

জাভাতে আপকাস্টিং অনুমোদিত, তবে ডাউনকাস্টিং একটি সংকলন ত্রুটি দেয়।

সংকলন ত্রুটি একটি কাস্ট যোগ করে অপসারণ করা যেতে পারে তবে রানটাইমের সময়ে যাই হোক না কেন।

এক্ষেত্রে জাভা কেন ডাউনটাইমিংয়ের অনুমতি দেয় যদি এটি রানটাইমে কার্যকর করা যায় না?
এই ধারণার জন্য কোন ব্যবহারিক ব্যবহার আছে?

public class demo {
  public static void main(String a[]) {
      B b = (B) new A(); // compiles with the cast, 
                         // but runtime exception - java.lang.ClassCastException
  }
}

class A {
  public void draw() {
    System.out.println("1");
  }

  public void draw1() {
    System.out.println("2");
  }
}

class B extends A {
  public void draw() {
    System.out.println("3");
  }
  public void draw2() {
    System.out.println("4");
  }
}

9
কোডের একটি স্নিপেট প্লাস এবং ত্রুটিটি এই ধারণাটি শিখার চেষ্টা করছে এমন লোকদের জন্য এটি আরও ভাল প্রশ্ন করে।
বব ক্রস

3
বব এর মন্তব্যের জন্য +1। প্রশ্নটি মোটেও পরিষ্কার নয়।
জন স্কিটি

আমি দেখি উপরের উদাহরণটি বেগ থেকে প্রকাশিত হয়েছে / ফোরামস / টি 151266- ডাউনকাস্টিং- প্রব্লেম.ইচটিএমএল যা ইতিমধ্যে কিছু ভাল উত্তর রয়েছে।
ফিলোহো

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

দয়া করে এটি সম্পাদনা করুন যাতে কোড স্নিপেটগুলি চারটি স্পেস দ্বারা ইন্টেন্ট করা থাকে। এটি ফর্ম্যাটিং ঠিক করবে।
পাতলা

উত্তর:


297

ডাউন কাস্টিং অনুমোদিত হয় যখন যখন সম্ভাবনা থাকে যে এটি রান সময়টিতে সফল হয়:

Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String

কিছু ক্ষেত্রে এটি সফল হবে না:

Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String

যখন রানটাইমে কোনও কাস্ট (যেমন শেষের মতো) ব্যর্থ হয় তখন ClassCastExceptionছুড়ে দেওয়া হবে।

অন্যান্য ক্ষেত্রে এটি কাজ করবে:

Object o = "a String";
String s = (String) o; // this will work, since o references a String

দ্রষ্টব্য যে কয়েকটি সংকলন সংকলনের সময় নিষিদ্ধ করা হবে, কারণ এগুলি কখনই সফল হবে না:

Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.

Object o = new Object(); String s = (String) o;এটা আমার জন্য ভাল কাজ করছে ..: ও কেমন?
আসিফ মোশতাক

@ অজানা: এটি করা উচিত নয়। আপনি যে সংস্করণটি আসলে সংকলন করেছেন এবং চালিত করেছেন তার দ্বিগুণ পরীক্ষা করুন এবং আপনি এখনও এটি পুনরুত্পাদন করতে পারলে একটি পৃথক প্রশ্ন পোস্ট করুন (একটি এসএসসিসিই সহ )।
জোচিম সৌর

@ জোয়াচিমসৌয়ার এই সংস্করণটির অর্থ কী? আমি জাভা 8 ব্যবহার করছি
আসিফ মোশতাক

1
@ অজানা: আমার অর্থ আপনার পোস্ট করা কোডটি চলবে না (এটি সংকলন করবে, তবে রানটাইমের সময় একটি ব্যতিক্রম ছুঁড়ে দেবে)। এই মন্তব্যগুলি ডিবাগ করার স্থান নয়। একটি পৃথক প্রশ্ন পোস্ট করুন।
জোছিম সৌর

রানটাইমে কাস্টিং কীভাবে ব্যর্থ হয়? টার্গেট অবজেক্ট রেফারেন্স সেট করে? ব্যতিক্রম ছুঁড়ে?
CygnusX1

17

আপনার উদাহরণ ব্যবহার করে আপনি এটি করতে পারেন:

public void doit(A a) {
    if(a instanceof B) {
        // needs to cast to B to access draw2 which isn't present in A
        // note that this is probably not a good OO-design, but that would
        // be out-of-scope for this discussion :)
        ((B)a).draw2();
    }
    a.draw();
}

যখন আমি আমার বিমূর্ত শ্রেণিটি একাধিক শ্রেণীর দ্বারা প্রসারিত হচ্ছিল তখন আমি উদাহরণের গুরুত্বটি শিখেছি এবং বিমূর্ত শ্রেণীর প্রকার উল্লেখ করে আমি সেই শ্রেণীর একচেটিয়া পদ্ধতিগুলি ব্যবহার করতে চাই। উদাহরণটি ব্যবহার না করে আমার ক্লাস কাস্ট ব্যতিক্রম ছিল
তরুন

16

আমি বিশ্বাস করি এটি স্ট্যাটিকালি টাইপ করা সমস্ত ভাষাতে প্রযোজ্য:

String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String

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

ব্যবহারিক ব্যবহারে, আপনি আরও সাধারণ শ্রেণিতে কাজ করে কোড লিখতে পারেন, তবে সাবক্লাসটি কী তা যদি আপনি জানেন এবং এটির মতো আচরণ করার প্রয়োজন হয় তবে এটি একটি সাবক্লাসে কাস্ট করতে পারেন। একটি সাধারণ উদাহরণ হল Object.equals () কে ওভাররাইড করা। ধরুন গাড়ীর জন্য আমাদের একটি ক্লাস রয়েছে:

@Override
boolean equals(Object o) {
    if(!(o instanceof Car)) return false;
    Car other = (Car)o;
    // compare this to other and return
}

আমি সত্যিই শব্দটি পছন্দ করি এবং আপনার পোস্টটিকে আরও
পরিচ্ছন্ন

5

আমরা সকলেই দেখতে পাচ্ছি যে আপনার প্রদত্ত কোডটি রান টাইমে কাজ করবে না। এর কারণ আমরা জানি যে এক্সপ্রেশনটি কখনই কোনও ধরণের বস্তু হতে new A()পারে নাB

সংকলক এটি দেখে না। সংকলকটি কাস্টের অনুমতি দেওয়া হয়েছে কিনা তা যাচাই করার সময় এটি কেবল এটি দেখবে:

variable_of_type_B = (B)expression_of_type_A;

এবং অন্যরা যেমন দেখিয়েছে, এই ধরণের castালাই পুরোপুরি আইনী। ডান দিকের অভিব্যক্তিটি টাইপের কোনও বস্তুর কাছে খুব ভাল মূল্যায়ন করতে পারে B। সংকলকটি এটি দেখে Aএবং Bএকটি উপ-টাইপ সম্পর্ক রাখে তাই কোডটির "এক্সপ্রেশন" ভিউয়ের সাথে, কাস্ট কাজ করতে পারে।

কম্পাইলারটি বিশেষ কেসটিকে বিবেচনা করে না যখন এটি জানে যে আসলে কী কী বস্তুর টাইপ expression_of_type_Aহবে। এটি কেবল স্থিতিশীল প্রকারটিকে দেখায় Aএবং গতিশীল Aধরণটি Aসহ বা এর কোনও বংশধর হতে পারে তা বিবেচনা করে B


3

এক্ষেত্রে জাভা কেন ডাউনটাইমিংয়ের অনুমতি দেয় যদি এটি রানটাইমে কার্যকর করা যায় না?

আমি বিশ্বাস করি এটি হ'ল কারণ এটি সংকলনটির সময় সংকলনের সময় জানার কোনও উপায় নেই যে কাস্টটি সফল হবে কি না। আপনার উদাহরণস্বরূপ, কাস্ট ব্যর্থ হবে তা দেখতে সহজ, তবে এমন অন্যান্য সময় রয়েছে যেখানে এটি এতটা পরিষ্কার নয়।

উদাহরণস্বরূপ, কল করুন যে বি, সি, এবং ডি সমস্ত প্রকারের প্রকার A প্রসারিত করে এবং তারপরে একটি পদ্ধতি public A getSomeA()এলোমেলোভাবে উত্পন্ন সংখ্যার উপর নির্ভর করে বি, সি বা ডি এর একটি উদাহরণ দেয়। সংকলকটি জানতে পারে না কোন সঠিক রান-টাইম টাইপটি এই পদ্ধতি দ্বারা ফিরে আসবে, সুতরাং আপনি পরে যদি ফলাফলটি ফেলে দেন Bতবে কাস্ট সফল হবে (বা ব্যর্থ হবে) তা জানার কোনও উপায় নেই। অতএব সংকলকটি ধরে নিয়েছে কাস্টগুলি সফল হবে।


2

@ মূল পোস্টার - ইনলাইন মন্তব্য দেখুন।

public class demo 
{
    public static void main(String a[]) 
    {
        B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException 
        //- A subclass variable cannot hold a reference to a superclass  variable. so, the above statement will not work.

        //For downcast, what you need is a superclass ref containing a subclass object.
        A superClassRef = new B();//just for the sake of illustration
        B subClassRef = (B)superClassRef; // Valid downcast. 
    }
}

class A 
{
    public void draw() 
    {
        System.out.println("1");
    }

    public void draw1() 
    {
        System.out.println("2");
    }
}

class B extends A 
{
    public void draw() 
    {
        System.out.println("3");
    }

    public void draw2() 
    {
        System.out.println("4");
    }
}

1

ডাউনকাস্ট ক্ষেত্রে কাজ করে যখন আমরা একটি উপবিষ্ট বস্তুর সাথে কাজ করি। Upcasting:

int intValue = 10;
Object objValue = (Object) intvalue;

সুতরাং এখন এই objValueপরিবর্তনশীলটি সর্বদা ডাউনকেস্ট করা যেতে পারে intকারণ যে বস্তুটি নিক্ষেপ করা হয়েছিল তা হ'ল একটি Integer,

int oldIntValue = (Integer) objValue;
// can be done 

তবে objValueএকটি অবজেক্ট হওয়ায় এটিকে কাস্ট করা যায় না Stringকারণ এতে কাস্ট করা intযায় না String


0

ডাউন কোডিং নীচের কোড স্নিপেটে আমি এটি সর্বদা ব্যবহার করি যাতে খুব দরকারী। সুতরাং প্রমাণিত যে ডাউনকাস্টিং দরকারী।

private static String printAll(LinkedList c)
{
    Object arr[]=c.toArray();
    String list_string="";
    for(int i=0;i<c.size();i++)
    {
        String mn=(String)arr[i];
        list_string+=(mn);
    }
    return list_string;
}

আমি স্ট্রিংকে লিঙ্কযুক্ত তালিকায় রাখি। আমি যখন লিঙ্কযুক্ত তালিকার উপাদানগুলি পুনরুদ্ধার করি তখন অবজেক্টগুলি ফিরে আসে। স্ট্রিংস (বা অন্য কোনও ক্লাস অবজেক্টস) হিসাবে উপাদানগুলিতে অ্যাক্সেস করতে ডাউনকাস্টিং আমাকে সহায়তা করে।

জাভা আমাদের উপর নির্ভর করে ডাউনকাস্ট কোড সংকলন করতে দেয় যে আমরা ভুল কাজ করছি। তবুও যদি মানুষ কোনও ভুল করে তবে রানটাইমের সময় এটি ধরা পড়ে।


জাভাতে অ জেনেরিক সংগ্রহগুলি ব্যবহার করা void*সি ++ এর পয়েন্টারের সমতুল্য । এটি আমার কাছে মোটেই ভাল ধারণার মতো শোনাচ্ছে না।
জিজোর

0

নীচের উদাহরণ বিবেচনা করুন

public class ClastingDemo {

/**
 * @param args
 */
public static void main(String[] args) {
    AOne obj = new Bone();
    ((Bone) obj).method2();
}
}

class AOne {
public void method1() {
    System.out.println("this is superclass");
}
}


 class Bone extends AOne {

public void method2() {
    System.out.println("this is subclass");
}
}

এখানে আমরা সাবক্লাস হাড়ের অবজেক্টটি তৈরি করে এটিকে সুপার ক্লাস এওন রেফারেন্সে অর্পণ করেছি এবং এখন সুপারক্লাস রেফারেন্স সাবক্লাসে পদ্ধতি পদ্ধতি 2 সম্পর্কে জানে না সংকলনের সময় হাড়। সুতরাং আমাদের সুপারক্লাসের এই রেফারেন্সটিকে সাবক্লাসের রেফারেন্সে ডাউনকাস্ট করতে হবে। ফলস্বরূপ উল্লেখটি সাবক্লাসে হাড়ের পদ্ধতিগুলির উপস্থিতি সম্পর্কে জানতে পারে


অয়ন কিছুটা বিভ্রান্ত দেখায়। দয়া করে আপনার শ্রেণীর নামগুলি কুকুর এবং প্রাণী বা
কোনও

0

জাভাতে ডাউনকাস্টিং করতে, এবং রান-টাইম ব্যতিক্রমগুলি এড়াতে নিম্নলিখিত কোডটির একটি রেফারেন্স নিন:

if (animal instanceof Dog) {
  Dog dogObject = (Dog) animal;
}

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


0

অবজেক্টগুলির ডাউনকাস্টিং রূপান্তর সম্ভব নয়। কেবল

DownCasting1 _downCasting1 = (DownCasting1)((DownCasting2)downCasting1);

সুস্পষ্ট

class DownCasting0 {
    public int qwe() {
        System.out.println("DownCasting0");
        return -0;
    }
}

class DownCasting1 extends DownCasting0 {
    public int qwe1() {
        System.out.println("DownCasting1");
        return -1;
    }
}

class DownCasting2 extends DownCasting1 {
    public int qwe2() {
        System.out.println("DownCasting2");
        return -2;
    }
}

public class DownCasting {

    public static void main(String[] args) {

        try {
            DownCasting0 downCasting0 = new DownCasting0();
            DownCasting1 downCasting1 = new DownCasting1();
            DownCasting2 downCasting2 = new DownCasting2();

            DownCasting0 a1 = (DownCasting0) downCasting2;
            a1.qwe(); //good

            System.out.println(downCasting0 instanceof  DownCasting2);  //false
            System.out.println(downCasting1 instanceof  DownCasting2);  //false
            System.out.println(downCasting0 instanceof  DownCasting1);  //false

            DownCasting2 _downCasting1= (DownCasting2)downCasting1;     //good
            DownCasting1 __downCasting1 = (DownCasting1)_downCasting1;  //good
            DownCasting2 a3 = (DownCasting2) downCasting0; // java.lang.ClassCastException

            if(downCasting0 instanceof  DownCasting2){ //false
                DownCasting2 a2 = (DownCasting2) downCasting0;
                a2.qwe(); //error
            }

            byte b1 = 127;
            short b2 =32_767;
            int b3 = 2_147_483_647;
//          long _b4 = 9_223_372_036_854_775_807; //int large number max 2_147_483_647
            long b4 = 9_223_372_036_854_775_807L;
//          float _b5 = 3.4e+038; //double default
            float b5 = 3.4e+038F; //Sufficient for storing 6 to 7 decimal digits
            double b6 = 1.7e+038;
            double b7 = 1.7e+038D; //Sufficient for storing 15 decimal digits

            long c1 = b3;
            int c2 = (int)b4;

            //int       4 bytes     Stores whole numbers from -2_147_483_648 to 2_147_483_647
            //float     4 bytes     Stores fractional numbers from 3.4e−038 to 3.4e+038. Sufficient for storing 6 to 7 decimal digits
            float c3 = b3; //logic error
            double c4 = b4; //logic error


        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.