سؤال

هناك مواقف، حيث يكون من العملي أن تقوم عملية type-cast بإرجاع قيمة فارغة بدلاً من طرح ClassCastException.يحتوي C# على as المشغل للقيام بذلك.هل هناك شيء مكافئ متاح في Java حتى لا تضطر إلى التحقق بشكل صريح من ClassCastException؟

هل كانت مفيدة؟

المحلول

فيما يلي تطبيق لـ as، كما اقترحه @Omar Kooheji:

public static <T> T as(Class<T> clazz, Object o){
    if(clazz.isInstance(o)){
        return clazz.cast(o);
    }
    return null;
}

as(A.class, new Object()) --> null
as(B.class, new B())  --> B

نصائح أخرى

أعتقد أنه سيتعين عليك أن تدحرج بنفسك:

return (x instanceof Foo) ? (Foo) x : null;

يحرر:إذا كنت لا تريد أن يتعامل رمز العميل الخاص بك مع القيم الخالية، فيمكنك تقديم ملف كائن فارغ

interface Foo {
    public void doBar();
}
class NullFoo implements Foo {
    public void doBar() {} // do nothing
}
class FooUtils {
    public static Foo asFoo(Object o) {
        return (o instanceof Foo) ? (Foo) o : new NullFoo();
    }
}
class Client {
    public void process() {
        Object o = ...;
        Foo foo = FooUtils.asFoo(o);
        foo.doBar(); // don't need to check for null in client
    }
}

يمكنك استخدام ال instanceof الكلمة الأساسية بدلاً من C# is, ، ولكن لا يوجد شيء مثل as.

مثال:

if(myThing instanceof Foo) {
   Foo myFoo = (Foo)myThing; //Never throws ClassCastException
   ...
}

يمكنك كتابة طريقة فائدة ثابتة مثل هذا.لا أعتقد أنه قابل للقراءة بشكل رهيب، لكنه أفضل تقدير تقريبي لما تحاول القيام به.وإذا كنت تستخدم الواردات الثابتة فلن يكون الأمر سيئًا للغاية من حيث سهولة القراءة.

package com.stackoverflow.examples;
public class Utils {
    @SuppressWarnings("unchecked")
    public static <T> T safeCast(Object obj, Class<T> type) {
        if (type.isInstance(obj)) {
            return (T) obj;
        }
        return null;
    }
}

فيما يلي حالة اختبار توضح كيفية عملها (وأنها تعمل بالفعل).

package com.stackoverflow.examples;
import static com.stackoverflow.examples.Utils.safeCast;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import org.junit.Test;

public class UtilsTest {

    @Test
    public void happyPath() {
        Object x = "abc";
        String y = safeCast(x, String.class);
        assertNotNull(y);
    }

    @Test
    public void castToSubclassShouldFail() {
        Object x = new Object();
        String y = safeCast(x, String.class);
        assertNull(y);
    }

    @Test
    public void castToUnrelatedTypeShouldFail() {
        Object x = "abc";
        Integer y = safeCast(x, Integer.class);
        assertNull(y);
    }
}

في Java 8، يمكنك أيضًا استخدام بناء جملة الدفق مع الاختياري:

Object o = new Integer(1);

Optional.ofNullable(o)
        .filter(Number.class::isInstance)
        .map(Number.class::cast)
        .ifPresent(n -> System.out.print("o is a number"));

أظن أنه من الممكن أن تقوم بإنشاء عامل كمشغل

شيء مثل

as<T,Type> (left, right)  
which evaluates to 
if (typeof(left) == right)
   return (right)left
else
    return null

لست متأكدًا من كيفية القيام بذلك، فأنا أتقن لغة البرمجة C# في الوقت الحالي وقد أصبحت قبعتي في لغة Java مغبرة قليلاً منذ أن تركت الجامعة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top