هل من الممكن في Java التحقق مما إذا كانت حقول الكائنات فارغة ثم إضافة القيمة الافتراضية إلى جميع تلك السمات؟

StackOverflow https://stackoverflow.com/questions/2146129

  •  23-09-2019
  •  | 
  •  

سؤال

أحتاج إلى التأكد من عدم وجود سمة كائن لاغية وإضافة القيمة الافتراضية في حالة وجودها الفارغ. هل هناك أي طريقة سهلة للقيام بذلك ، أو هل يجب علي القيام بذلك يدويًا عن طريق التحقق من كل سمة من قبل GetTers والمستقبين؟

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

المحلول

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

for (Field f : obj.getClass().getFields()) {
  f.setAccessible(true);
  if (f.get(obj) == null) {
     f.set(obj, getDefaultValueForType(f.getType()));
  }
}

تحديث

مع Java الحديثة ، يمكنك استخدام التعليقات التوضيحية لتعيين القيم الافتراضية للحقول على أساس لكل فصل. قد يبدو التنفيذ الكامل هكذا:

// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultString {
    String value();
}

// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultInteger {
    int value();
}

// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class DefaultPojo {

    public void setDefaults() {
        for (Field f : getClass().getFields()) {
            f.setAccessible(true);
            try {
                if (f.get(this) == null) {
                    f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
                }
            } catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
            }
        }
    }

    private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
        for (Annotation a : annotations) {
            if (a instanceof DefaultString)
                return ((DefaultString)a).value();
            if (a instanceof DefaultInteger)
                return ((DefaultInteger)a).value();
        }
        return null;
    }

}

// Test Pojo
public class TestPojo extends DefaultPojo {
    @DefaultString("Hello world!")
    public String stringValue;
    @DefaultInteger(42);
    public int integerValue;
}

ثم القيم الافتراضية ل TestPojo يمكن ضبطها فقط عن طريق الجري test.setDetaults()

نصائح أخرى

تحتاج إلى تصفية المدخلات يدويًا إلى المُنشئين والمستقبين. حسنًا ... يمكنك استخدام التفكير ولكني لن أنصح ذلك. جزء من وظيفة البنائين والمستقلين هو التحقق من صحة المدخلات. يمكن أن تشمل أشياء مثل:

public void setPrice(double price) {
  if (price < 0.0d) {
    throw new IllegalArgumentException("price cannot be negative " + price);
  }
  this.price = price;
}

و

public void setName(String name) {
  if (name == null) {
    throw new NullPointerException("name cannot be null");
  }
  this.name = name;
}

يمكنك استخدام وظائف الغلاف للفحص الفعلي ورمي الاستثناء.

ربما تحقق صحة السبات 4.0, ، التنفيذ المرجعي ل JSR 303: التحقق من صحة الفول.

هذا مثال على الفصل المشروح:

public class Address {

    @NotNull 
    private String line1;
    private String line2;
    private String zip;
    private String state;

    @Length(max = 20)
    @NotNull
    private String country;

    @Range(min = -2, max = 50, message = "Floor out of range")
    public int floor;

        ...
}

للحصول على مقدمة ، انظر البدء مع JSR 303 (التحقق من صحة الفول) - الجزء 1 و الجزء 2 أو قسم "البدء" في الدليل المرجعي والذي يعد جزءًا من توزيع مصادقة السبات.

الحل غير العاكس لـ Java 8 ، دون استخدام سلسلة من IF ، سيكون دفق جميع الحقول والتحقق من الإيلاء:

return Stream.of(id, name).allMatch(Objects::isNull);

لا يزال هذا سهل الحفاظ عليه مع تجنب مطرقة الانعكاس. هذا سيعود صحيح للسمات الفارغة.

يمكنك إنشاء وظيفة تُرجع قيمة منطقية وتتحقق من كل سمة. يمكنك استدعاء هذه الوظيفة للقيام بالمهمة لك.

بدلاً من ذلك ، يمكنك تهيئة الكائن بالقيم الافتراضية. بهذه الطريقة ليست هناك حاجة لك للقيام بأي فحص.

ليس لدي سياق كافٍ لإعطائك إجابة صحيحة ، لكنني أقترح عليك أن تجعلك رمزًا ثابت بقدر المستطاع. يستخدم public final مجالات. لا أكثر getters أو setters : يجب تعريف كل حقل بواسطة constructor. الكود الخاص بك أقصر وأكثر قابلية للقراءة ويمنعك من كتابة التعليمات البرمجية مع الآثار الجانبية.

لا يمنعك ذلك من تمرير الوسائط الخالية إلى مُنشرك على الرغم من ... لا يزال بإمكانك التحقق من كل وسيطة كما اقترحها @ @، لكنني أقترح عليك رمي IllegalArgumentException بدلاً من NullPointerException هذا لا يعطي أي تلميح جديد حول ما قمت به.

على أي حال ، هذا ما أفعله بقدر ما أستطيع ، وقد حسّن الكود (قابلية القراءة ، الاستقرار) إلى تمديد كبير. كل شخص في فريقي يفعل ذلك ونحن سعداء جدا بذلك. لقد تعلمنا أنه عندما نحاول كتابة بعض erlang رمز حيث كل شيء غير قابل للتغيير.

أتمنى أن يساعدك هذا.

لقد جربت هذا وهو يعمل دون أي مشاكل للتحقق من صحة ما إذا كان الحقل فارغًا. لقد أجبت على سؤالك جزئيًا لأنني لم أحاول شخصيا إضافة قيم افتراضية إلى السمات

if(field.getText()!= null && !field.getText().isEmpty())

أتمنى أن يساعد ذلك

هذا ليس للتحقق من NULL ، بدلاً من ذلك سيكون هذا مفيدًا في تحويل كائن موجود إلى كائن فارغ (كائن جديد). لا أعرف ما إذا كان هذا مناسبًا أم لا ، لكن كان لدي مثل هذا الشرط.

@SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj) 
{
    Class c1 = obj.getClass();
    Field[] fields = c1.getDeclaredFields();

    for(Field field : fields)
    {
        try
        {
            if(field.getType().getCanonicalName() == "boolean")
            {
                field.set(obj, false);
            }
            else if(field.getType().getCanonicalName() == "char")
            {
                field.set(obj, '\u0000');
            }
            else if((field.getType().isPrimitive()))
            {
                field.set(obj, 0);
            }
            else
            {
                field.set(obj, null);
            }
        }
        catch(Exception ex)
        {

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