পদ্ধতি আর্গুমেন্টে নোটনাল টিকা ব্যবহার করে


156

আমি সবেমাত্র @NotNullজাভা 8 এর সাথে টিকাটি ব্যবহার শুরু করেছি এবং কিছু অপ্রত্যাশিত ফলাফল পেয়েছি ।

আমার এই জাতীয় পদ্ধতি রয়েছে:

public List<Found> findStuff(@NotNull List<Searching> searchingList) {
    ... code here ...
}

আমি যুক্তি অনুসন্ধানের তালিকার জন্য নাল মান দিয়ে পাস করে একটি JUnit পরীক্ষা লিখেছি। আমি প্রত্যাশা করছিলাম যে কোনও ধরণের ত্রুটি ঘটবে তবে এটি এমনভাবে ঘটেছিল যে টীকাটি ছিল না। এই প্রত্যাশিত আচরণ? আমি যা বুঝতে পেরেছি তা থেকে এটি আপনাকে বয়লারপ্লেট নাল চেক কোডটি লেখার এড়াতে দেয়।

@ নটনুল ঠিক কী করার কথা বলেছে তার একটি ব্যাখ্যা প্রশংসিত হবে।


29
@NotNullএটি কেবল একটি টীকা। টীকাগুলি নিজেরাই কিছু করে না। তাদের সংকলন সময়ে একটি টীকা প্রসেসর, বা রানটাইম সময়ে এটি প্রক্রিয়া করে এমন কিছু দরকার।
সোটিরিওস ডেলিমানলিস

আপনি কি কোনও অ্যাপ্লিকেশন সার্ভারের মধ্যে কোড চালাচ্ছেন (উদাহরণস্বরূপ আরকিলিয়ান ব্যবহার করে )?
jabu.10245

1
@ সোতিরিওসডেলিমনোলিস - তাহলে কী কথা, যে কেউ এই পদ্ধতিটি নাল মান পাস না করার আহ্বান জানাতে কেবল একটি সতর্কতা? সেক্ষেত্রে আপনার এখনও নাল পয়েন্টার বৈধকরণ কোডের প্রয়োজন।
ডেভিডআর

1
হাইবারনেট ভ্যালিডেটরটি দেখুন
arisalexis

@ jabu.10245 - কোনও অ্যাপ্লিকেশন সার্ভার ব্যবহার করছে না।
ডেভিডআর

উত্তর:


183

@Nullableএবং @NotNullনিজেরাই কিছু করবেন না। তাদের ডকুমেন্টেশন সরঞ্জাম হিসাবে কাজ করার কথা রয়েছে।

@Nullableটীকা অপরিহার্যতা একটি NPE চেক যখন পরিচয় করিয়ে দিতে সম্পর্কে আপনাকে মনে করিয়ে দেয়:

  1. কল করার পদ্ধতিগুলি নাল ফিরতে পারে।
  2. ভেরিয়েবল (ক্ষেত্র, স্থানীয় ভেরিয়েবল, পরামিতি) নির্ধারণ করা যা শূন্য হতে পারে।

@NotNullটীকা, আসলে হয় একটি সুনির্দিষ্ট চুক্তি নিম্নলিখিত প্রকাশক:

  1. একটি পদ্ধতি নাল ফিরে উচিত নয়।
  2. একটি পরিবর্তনশীল (ক্ষেত্র, স্থানীয় ভেরিয়েবল, এবং পরামিতি মত) করতে পারবেন না করা উচিত নয় নাল মান ধরে রাখুন।

উদাহরণস্বরূপ, লেখার পরিবর্তে:

/**
 * @param aX should not be null
 */
public void setX(final Object aX ) {
    // some code
}

তুমি ব্যবহার করতে পার:

public void setX(@NotNull final Object aX ) {
    // some code
}

অধিকন্তু, @NotNullপ্রায়শই কনস্ট্রেন্টভ্যালিডেটর (যেমন: বসন্ত এবং হাইবারনেটে) দ্বারা পরীক্ষা করা হয় ।

@NotNullটীকা তার নিজের উপর কোনো বৈধতা করে না কারণ টীকা সংজ্ঞা কোনো উপলব্ধ করা হয় না ConstraintValidatorটাইপ রেফারেন্স।

আরও তথ্যের জন্য দেখুন:

  1. বিনের বৈধতা
  2. NotNull.java
  3. Constraint.java
  4. ConstraintValidator.java

3
সুতরাং কেবল নটনুল অংশের ২ য় অংশটি স্পষ্ট করার জন্য, এটি অবশ্যই বলা উচিত "উচিত নয়", না "না" যেহেতু এটি বিছানা প্রয়োগ করতে পারে না? অথবা যদি রানটাইমে প্রয়োগ করা যায় তবে আপনি কীভাবে তা চালিয়ে যাবেন?
ডেভিডআর

হ্যাঁ, এটির একটি "উচিত নয়" ... পদ্ধতি প্রয়োগের চুক্তিটি কার্যকর করা উচিত।
justAnotherUser ...

1
বিকল্পভাবে, জাভা 8-এ, রিটার্ন মানগুলির জায়গায় এবং প্যারামিটার তালিকার জায়গায় পদ্ধতি ওভারলোডিং Optionalব্যবহার করা যেতে পারে : ডলসজেউসকি@Null@Null
চাদ কে

13
আমি বিশ্বাস করি যে বিভ্রান্তি নোটনাল টীকাটির জাভা ডক থেকে এসেছে: * The annotated element must not be {@code null}. * Accepts any type.এবং আমি মনে করি অবশ্যই শব্দটি অবশ্যই প্রতিস্থাপন করা উচিত তবে এটি আপনি কীভাবে পড়বেন তার উপর নির্ভর করে। অবশ্যই আরও কিছু স্পষ্টতা থাকা ভাল হবে
জুলিয়ান

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

27

উপরে উল্লিখিত হিসাবে @NotNullনিজস্ব কিছু করে না। ব্যবহারের একটি ভাল উপায় এটি ব্যবহার করা @NotNullহবেObjects.requireNonNull

public class Foo {
    private final Bar bar;

    public Foo(@NotNull Bar bar) {
        this.bar = Objects.requireNonNull(bar, "bar must not be null");
    }
}

6
শুধু একটি টিপ। আপনি এই লাইনে একটি লাইনের মাধ্যমেও লিখতে পারেন:this.bar = Objects.requireNonNull(bar, "bar must not be null");
লোলং

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


6

সুতরাং @ নটনুল কেবল একটি ট্যাগ ... আপনি যদি এটি যাচাই করতে চান তবে আপনাকে অবশ্যই হাইবারনেট ভ্যালিডেটর জেএসআর 303 এর মতো কিছু ব্যবহার করতে হবে

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
 Set<ConstraintViolation<List<Searching>> violations = validator.validate(searchingList);

পদ্ধতিটির শুরুতে আমি এটি কোথায় রাখি?
ডেভিডআর

হ্যাঁ ... পদ্ধতির শুরুতে ... এটি বৈধতা বাস্তবায়নগুলির মধ্যে একটি মাত্র, অন্যরাও থাকতে পারেন ...
নারুটো

ঠিক আছে. কিন্তু সেই কোডটি কী করে তার এই তাত্পর্যটি পরিবর্তিত হবে না আমার কাছে প্যারাম যুক্তিতে @ নটনুল টিকা আছে কিনা?
ডেভিডআর

এখন আপনার সেটে সমস্ত লঙ্ঘন রয়েছে, এর আকারটি যদি শূন্যের থেকে বড় হয় তবে এটি পরীক্ষা করুন method
নারুটো

3

আপনি যদি স্প্রিং ব্যবহার করছেন, আপনি ক্লাসটি এটিকে বেনিফিট করে বৈধতা প্রয়োগ করতে পারেন @Validated:

import org.springframework.validation.annotation.Validated;

এখানে আরও তথ্য উপলব্ধ: জাভাক্স বৈধতা @ নট নোট টিকা ব্যবহারের জন্য usage


2

আমি আমার নিজস্ব বৈধতা টীকা এবং যাচাইকারী তৈরি করতে এটি করি:

ValidCardType.java(পদ্ধতি / ক্ষেত্রের উপর টীকায়িত টীকা)

@Constraint(validatedBy = {CardTypeValidator.class})
@Documented
@Target( { ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidCardType {
    String message() default "Incorrect card type, should be among: \"MasterCard\" | \"Visa\"";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

এবং, যাচাইকারী চেকটি ট্রিগার করতে CardTypeValidator.java:

public class CardTypeValidator implements ConstraintValidator<ValidCardType, String> {
    private static final String[] ALL_CARD_TYPES = {"MasterCard", "Visa"};

    @Override
    public void initialize(ValidCardType status) {
    }
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return (Arrays.asList(ALL_CARD_TYPES).contains(value));
    }
}

আপনি চেক অনুরূপ কিছু করতে পারেন @NotNull


0

একটি পরীক্ষায় আপনার পদ্ধতির বৈধতা পরীক্ষা করতে, আপনাকে এটি @ পূর্ব পদ্ধতিতে একটি প্রক্সি মোড়তে হবে।

@Before
public void setUp() {
    this.classAutowiredWithFindStuffMethod = MethodValidationProxyFactory.createProxy(this.classAutowiredWithFindStuffMethod);
}

মেথডভ্যালিডেশনপ্রক্সি ফ্যাক্টরি সহ:

import org.springframework.context.support.StaticApplicationContext;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

public class MethodValidationProxyFactory {

private static final StaticApplicationContext ctx = new StaticApplicationContext();

static {
    MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
    processor.afterPropertiesSet(); // init advisor
    ctx.getBeanFactory()
            .addBeanPostProcessor(processor);
}

@SuppressWarnings("unchecked")
public static <T> T createProxy(T instance) {

    return (T) ctx.getAutowireCapableBeanFactory()
            .applyBeanPostProcessorsAfterInitialization(instance, instance.getClass()
                    .getName());
}

}

এবং তারপরে, আপনার পরীক্ষা যুক্ত করুন:

@Test
public void findingNullStuff() {
 assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> this.classAutowiredWithFindStuffMethod.findStuff(null));

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