এই UtilException
সহায়ক শ্রেণিটি আপনাকে জাভা স্ট্রিমগুলিতে যেকোনো চেক করা ব্যতিক্রমগুলি ব্যবহার করতে দেয়:
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
.map(rethrowFunction(Class::forName))
.collect(Collectors.toList());
নোট Class::forName
নিক্ষেপ ClassNotFoundException
, যা চেক করা হয় । স্ট্রিমটি নিজেও ছুঁড়েছে ClassNotFoundException
, এবং কিছু মোড়ানো চেক করা ব্যতিক্রম নয়।
public final class UtilException {
@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
void accept(T t) throws E;
}
@FunctionalInterface
public interface BiConsumer_WithExceptions<T, U, E extends Exception> {
void accept(T t, U u) throws E;
}
@FunctionalInterface
public interface Function_WithExceptions<T, R, E extends Exception> {
R apply(T t) throws E;
}
@FunctionalInterface
public interface Supplier_WithExceptions<T, E extends Exception> {
T get() throws E;
}
@FunctionalInterface
public interface Runnable_WithExceptions<E extends Exception> {
void run() throws E;
}
/** .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); or .forEach(rethrowConsumer(ClassNameUtil::println)); */
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
return t -> {
try { consumer.accept(t); }
catch (Exception exception) { throwAsUnchecked(exception); }
};
}
public static <T, U, E extends Exception> BiConsumer<T, U> rethrowBiConsumer(BiConsumer_WithExceptions<T, U, E> biConsumer) throws E {
return (t, u) -> {
try { biConsumer.accept(t, u); }
catch (Exception exception) { throwAsUnchecked(exception); }
};
}
/** .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName)) */
public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
return t -> {
try { return function.apply(t); }
catch (Exception exception) { throwAsUnchecked(exception); return null; }
};
}
/** rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))), */
public static <T, E extends Exception> Supplier<T> rethrowSupplier(Supplier_WithExceptions<T, E> function) throws E {
return () -> {
try { return function.get(); }
catch (Exception exception) { throwAsUnchecked(exception); return null; }
};
}
/** uncheck(() -> Class.forName("xxx")); */
public static void uncheck(Runnable_WithExceptions t)
{
try { t.run(); }
catch (Exception exception) { throwAsUnchecked(exception); }
}
/** uncheck(() -> Class.forName("xxx")); */
public static <R, E extends Exception> R uncheck(Supplier_WithExceptions<R, E> supplier)
{
try { return supplier.get(); }
catch (Exception exception) { throwAsUnchecked(exception); return null; }
}
/** uncheck(Class::forName, "xxx"); */
public static <T, R, E extends Exception> R uncheck(Function_WithExceptions<T, R, E> function, T t) {
try { return function.apply(t); }
catch (Exception exception) { throwAsUnchecked(exception); return null; }
}
@SuppressWarnings ("unchecked")
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E { throw (E)exception; }
}
এটি কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও অনেক উদাহরণ (স্থিতিশীলভাবে আমদানির পরে UtilException
):
@Test
public void test_Consumer_with_checked_exceptions() throws IllegalAccessException {
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
.forEach(rethrowConsumer(className -> System.out.println(Class.forName(className))));
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
.forEach(rethrowConsumer(System.out::println));
}
@Test
public void test_Function_with_checked_exceptions() throws ClassNotFoundException {
List<Class> classes1
= Stream.of("Object", "Integer", "String")
.map(rethrowFunction(className -> Class.forName("java.lang." + className)))
.collect(Collectors.toList());
List<Class> classes2
= Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
.map(rethrowFunction(Class::forName))
.collect(Collectors.toList());
}
@Test
public void test_Supplier_with_checked_exceptions() throws ClassNotFoundException {
Collector.of(
rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))),
StringJoiner::add, StringJoiner::merge, StringJoiner::toString);
}
@Test
public void test_uncheck_exception_thrown_by_method() {
Class clazz1 = uncheck(() -> Class.forName("java.lang.String"));
Class clazz2 = uncheck(Class::forName, "java.lang.String");
}
@Test (expected = ClassNotFoundException.class)
public void test_if_correct_exception_is_still_thrown_by_method() {
Class clazz3 = uncheck(Class::forName, "INVALID");
}
তবে নিম্নলিখিত সুবিধা, অসুবিধাগুলি এবং সীমাবদ্ধতাগুলি বোঝার আগে এটি ব্যবহার করবেন না :
The যদি কলিং-কোডটি চেক করা ব্যতিক্রমটি পরিচালনা করতে হয় তবে আপনি এটি স্ট্রিমযুক্ত পদ্ধতির থ্রোস ক্লোজে যুক্ত করতে হবে। সংকলকটি আপনাকে এটি আর যুক্ত করতে বাধ্য করবে না, তাই এটি ভুলে যাওয়া সহজ।
The যদি কলিং-কোডটি ইতিমধ্যে চেক করা ব্যতিক্রমগুলি পরিচালনা করে তবে সংকলকটি আপনাকে স্ট্রিমটি সম্বলিত পদ্ধতি ঘোষণায় থ্রোস ক্লজ যুক্ত করার জন্য স্মরণ করিয়ে দেবে (যদি আপনি এটি বলেন না যে: ব্যতিক্রমটি সংশ্লিষ্ট চেষ্টা স্টেটমেন্টের শিরোনামে কখনও ছুঁড়ে দেওয়া হয় না) )।
Case যে কোনও ক্ষেত্রে, আপনি পরীক্ষা করা ব্যতিক্রমটি ধরতে স্ট্রিমের চারপাশে নিজেকে ঘিরে রাখতে সক্ষম হবেন না the যে স্ট্রিমটি রয়েছে সেই পদ্ধতিতে (যদি আপনি চেষ্টা করেন, সংকলকটি বলবে: ব্যতিক্রমটি সংশ্লিষ্ট চেষ্টা বিবৃতিতে কোনও দিনই ছোঁড়া হয় না)।
You আপনি যদি এমন কোনও পদ্ধতিতে কল করছেন যা আক্ষরিকরূপে এটি যে ব্যতিক্রম ঘোষণা করে তা কখনই ফেলতে পারে না, তবে আপনার থ্রো ক্লজটি অন্তর্ভুক্ত করা উচিত নয়। উদাহরণস্বরূপ: নতুন স্ট্রিং (বাইটআরআর, "ইউটিএফ -8") অসমর্থিত এনকোডিংএক্সসেপশন ছুঁড়েছে, তবে ইউটিএফ -8 সর্বদা উপস্থিত থাকার জন্য জাভা স্পেস দ্বারা গ্যারান্টিযুক্ত। এখানে, থ্রো ডিক্লোরেশনটি একটি উপদ্রব এবং এটি ন্যূনতম বয়লারপ্লেট দিয়ে চুপ করার কোনও সমাধান স্বাগত।
You আপনি যদি চেক করা ব্যতিক্রমগুলি ঘৃণা করেন এবং মনে করেন যে এগুলি শুরু করার জন্য জাভা ভাষার সাথে আর যুক্ত করা উচিত নয় (ক্রমবর্ধমান সংখ্যক লোকেরা এইভাবে মনে করেন, এবং আমি তাদের মধ্যে কেউ নই), তবে কেবলমাত্র চেক করা ব্যতিক্রমটি যুক্ত করবেন না স্ট্রিম রয়েছে এমন পদ্ধতির ধারাটি ছুড়ে ফেলে। চেক করা ব্যতিক্রমগুলি তখন একটি চেক করা ব্যতিক্রমের মতো আচরণ করবে।
You আপনি যদি একটি কঠোর ইন্টারফেস প্রয়োগ করছেন যেখানে আপনার কাছে ছোঁড়া ঘোড়া ঘোষণার যোগ করার বিকল্প নেই, এবং এখনও একটি ব্যতিক্রম ছুঁড়ে দেওয়া সম্পূর্ণ উপযুক্ত, তবে কেবল নিক্ষিপ্ত ব্যতিক্রমগুলি স্ট্যাকট্রেসে ফলাফল ছুঁড়ে ফেলার অধিকার অর্জনের জন্য একটি ব্যতিক্রম মোড়ানো pping যা আসলে কী ভুল হয়েছে সে সম্পর্কে কোনও তথ্য অবদান রাখে না। একটি ভাল উদাহরণ রান্নেবল.আরুন (), যা কোনও পরীক্ষিত ব্যতিক্রম ছুঁড়ে না ফেলে। এই ক্ষেত্রে, আপনি স্ট্রিম রয়েছে এমন পদ্ধতির থ্রো ক্লজে চেক করা ব্যতিক্রমটি যুক্ত না করার সিদ্ধান্ত নিতে পারেন।
Any যে কোনও ক্ষেত্রে, আপনি যদি স্ট্রিম রয়েছে এমন পদ্ধতির ছোঁড়া অনুচ্ছেদে চেক করা ব্যতিক্রম যুক্ত (বা যুক্ত করতে ভুলবেন না) তবে চেকড ব্যতিক্রম ছোঁড়ার এই 2 পরিণতি সম্পর্কে সচেতন হন:
1) কলিং-কোড নামটি এটি ধরতে সক্ষম হবে না (যদি আপনি চেষ্টা করেন, সংকলকটি বলবে: ব্যতিক্রমটি সংশ্লিষ্ট চেষ্টা বিবৃতিতে কোনও দিনই ছোঁড়া হয় না)। এটি বুদবুদ হবে এবং সম্ভবত কিছু "ক্যাচ এক্সেপশন" বা "ক্যাচ থ্রোয়েবল" দ্বারা মূল প্রোগ্রামের লুপে ধরা হবে, যা আপনি যাইহোক চান তা হতে পারে।
2) এটি সর্বনিম্ন আশ্চর্যের নীতি লঙ্ঘন করে: সমস্ত সম্ভাব্য ব্যতিক্রম ধরা গ্যারান্টি দিতে সক্ষম হওয়ার জন্য রানটাইম এক্সেকশনকে ধরে নেওয়া এখন আর যথেষ্ট হবে না। এই কারণে, আমি বিশ্বাস করি এটি ফ্রেমওয়ার্ক কোডে করা উচিত নয়, তবে কেবলমাত্র এমন ব্যবসায়িক কোডে যা আপনি সম্পূর্ণরূপে নিয়ন্ত্রণ করেন।
উপসংহারে: আমি বিশ্বাস করি যে এখানে সীমাবদ্ধতাগুলি গুরুতর নয় এবং UtilException
ক্লাসটি নির্ভয়ে ব্যবহার করা যেতে পারে। তবে এটি আপনার উপর!