Jawaban:
varargs bisa melakukan itu (dengan cara tertentu). Selain itu, semua variabel dalam deklarasi metode harus disediakan. Jika Anda ingin variabel menjadi opsional, Anda bisa membebani metode menggunakan tanda tangan yang tidak memerlukan parameter.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Ada beberapa cara untuk mensimulasikan parameter opsional di Jawa:
Metode kelebihan beban.
void foo(String a, Integer b) {
//...
}
void foo(String a) {
foo(a, 0); // here, 0 is a default value for b
}
foo("a", 2);
foo("a");
Salah satu batasan dari pendekatan ini adalah bahwa itu tidak berfungsi jika Anda memiliki dua parameter opsional dari jenis yang sama dan salah satu dari mereka dapat dihilangkan.
Varargs.
a) Semua parameter opsional memiliki tipe yang sama:
void foo(String a, Integer... b) {
Integer b1 = b.length > 0 ? b[0] : 0;
Integer b2 = b.length > 1 ? b[1] : 0;
//...
}
foo("a");
foo("a", 1, 2);
b) Jenis parameter opsional mungkin berbeda:
void foo(String a, Object... b) {
Integer b1 = 0;
String b2 = "";
if (b.length > 0) {
if (!(b[0] instanceof Integer)) {
throw new IllegalArgumentException("...");
}
b1 = (Integer)b[0];
}
if (b.length > 1) {
if (!(b[1] instanceof String)) {
throw new IllegalArgumentException("...");
}
b2 = (String)b[1];
//...
}
//...
}
foo("a");
foo("a", 1);
foo("a", 1, "b2");
Kelemahan utama dari pendekatan ini adalah bahwa jika parameter opsional dari tipe yang berbeda Anda kehilangan pemeriksaan tipe statis. Lebih jauh, jika setiap parameter memiliki arti yang berbeda, Anda perlu cara untuk membedakannya.
Nulls. Untuk mengatasi keterbatasan pendekatan sebelumnya, Anda dapat mengizinkan nilai nol dan kemudian menganalisis setiap parameter dalam tubuh metode:
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
Sekarang semua nilai argumen harus disediakan, tetapi yang standar mungkin nol.
Kelas opsional. Pendekatan ini mirip dengan nol, tetapi menggunakan kelas Java 8 Opsional untuk parameter yang memiliki nilai default:
void foo(String a, Optional<Integer> bOpt) {
Integer b = bOpt.isPresent() ? bOpt.get() : 0;
//...
}
foo("a", Optional.of(2));
foo("a", Optional.<Integer>absent());
Opsional membuat metode kontrak eksplisit untuk penelepon, namun, orang mungkin menemukan tanda tangan seperti itu terlalu lisan.
Pembaruan: Java 8 termasuk kelas java.util.Optional
out-of-the-box, jadi tidak perlu menggunakan jambu untuk alasan khusus ini di Jawa 8. Namun nama metode agak berbeda.
Pola pembangun. Pola pembangun digunakan untuk konstruktor dan diimplementasikan dengan memperkenalkan kelas Builder yang terpisah:
class Foo {
private final String a;
private final Integer b;
Foo(String a, Integer b) {
this.a = a;
this.b = b;
}
//...
}
class FooBuilder {
private String a = "";
private Integer b = 0;
FooBuilder setA(String a) {
this.a = a;
return this;
}
FooBuilder setB(Integer b) {
this.b = b;
return this;
}
Foo build() {
return new Foo(a, b);
}
}
Foo foo = new FooBuilder().setA("a").build();
Peta. Ketika jumlah parameter terlalu besar dan untuk sebagian besar nilai default biasanya digunakan, Anda bisa meneruskan argumen metode sebagai peta nama / nilai mereka:
void foo(Map<String, Object> parameters) {
String a = "";
Integer b = 0;
if (parameters.containsKey("a")) {
if (!(parameters.get("a") instanceof Integer)) {
throw new IllegalArgumentException("...");
}
a = (Integer)parameters.get("a");
}
if (parameters.containsKey("b")) {
//...
}
//...
}
foo(ImmutableMap.<String, Object>of(
"a", "a",
"b", 2,
"d", "value"));
Di Jawa 9, pendekatan ini menjadi lebih mudah:
@SuppressWarnings("unchecked")
static <T> T getParm(Map<String, Object> map, String key, T defaultValue)
{
return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
}
void foo(Map<String, Object> parameters) {
String a = getParm(parameters, "a", "");
int b = getParm(parameters, "b", 0);
// d = ...
}
foo(Map.of("a","a", "b",2, "d","value"));
Harap dicatat bahwa Anda dapat menggabungkan salah satu dari pendekatan ini untuk mencapai hasil yang diinginkan.
a
variabel Anda adalah String (pemeran adalah benar).
Ada parameter opsional dengan Java 5.0. Nyatakan fungsi Anda seperti ini:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
Anda bisa menelepon dengan doSomething();
atau doSomething(true);
sekarang.
doSomething() { doSomething(true); }
tidak ada array untuk ditangani, tidak ada ambiguitas
Anda dapat menggunakan sesuatu seperti ini:
public void addError(String path, String key, Object... params) {
}
Itu params
variabel adalah opsional. Itu diperlakukan sebagai array Objek nullable.
Anehnya, saya tidak dapat menemukan apa pun dalam dokumentasi ini, tetapi berhasil!
Ini "baru" di Java 1.5 dan yang lebih tinggi (tidak didukung di Java 1.4 atau sebelumnya).
Saya melihat pengguna bhoot menyebutkan ini juga di bawah.
Sayangnya Java tidak mendukung parameter default secara langsung.
Namun, saya telah menulis satu set anotasi JavaBean, dan salah satunya mendukung parameter default seperti berikut:
protected void process(
Processor processor,
String item,
@Default("Processor.Size.LARGE") Size size,
@Default("red") String color,
@Default("1") int quantity) {
processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
System.out.println("Message: " + message);
}
Prosesor anotasi menghasilkan kelebihan metode untuk mendukung hal ini dengan benar.
Lihat http://code.google.com/p/javadude/wiki/Annotations
Contoh lengkap di http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
VarArgs dan overloading telah disebutkan. Pilihan lain adalah pola Builder, yang akan terlihat seperti ini:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Meskipun pola itu akan paling tepat ketika Anda membutuhkan parameter opsional di konstruktor.
Dalam JDK> 1,5 Anda dapat menggunakannya seperti ini;
public class NewClass1 {
public static void main(String[] args) {
try {
someMethod(18); // Age : 18
someMethod(18, "John Doe"); // Age & Name : 18 & John Doe
} catch (Exception e) {
e.printStackTrace();
}
}
static void someMethod(int age, String... names) {
if (names.length > 0) {
if (names[0] != null) {
System.out.println("Age & Name : " + age + " & " + names[0]);
}
} else {
System.out.println("Age : " + age);
}
}
}
Anda dapat melakukan hal menggunakan metode kelebihan seperti ini.
public void load(String name){ }
public void load(String name,int age){}
Anda juga dapat menggunakan anotasi @Nullable
public void load(@Nullable String name,int age){}
cukup berikan null sebagai parameter pertama.
Jika Anda melewati variabel tipe yang sama Anda dapat menggunakan ini
public void load(String name...){}
Overloading baik-baik saja, tetapi jika ada banyak variabel yang membutuhkan nilai default, Anda akan berakhir dengan:
public void methodA(A arg1) { }
public void methodA( B arg2,) { }
public void methodA(C arg3) { }
public void methodA(A arg1, B arg2) { }
public void methodA(A arg1, C arg3) { }
public void methodA( B arg2, C arg3) { }
public void methodA(A arg1, B arg2, C arg3) { }
Jadi saya akan menyarankan gunakan Argumen Variabel yang disediakan oleh Java. Berikut tautan untuk penjelasan.
Anda bisa menggunakan kelas yang berfungsi seperti pembangun untuk memuat nilai opsional Anda seperti ini.
public class Options {
private String someString = "default value";
private int someInt= 0;
public Options setSomeString(String someString) {
this.someString = someString;
return this;
}
public Options setSomeInt(int someInt) {
this.someInt = someInt;
return this;
}
}
public static void foo(Consumer<Options> consumer) {
Options options = new Options();
consumer.accept(options);
System.out.println("someString = " + options.someString + ", someInt = " + options.someInt);
}
Gunakan seperti
foo(o -> o.setSomeString("something").setSomeInt(5));
Output adalah
someString = something, someInt = 5
Untuk melewati semua nilai opsional yang Anda harus suka foo(o -> {});
atau jika Anda suka, Anda dapat membuat yang keduafoo()
metode yang tidak mengambil parameter opsional.
Dengan menggunakan pendekatan ini, Anda dapat menentukan nilai opsional dalam urutan apa pun tanpa ambiguitas. Anda juga dapat memiliki parameter kelas yang berbeda tidak seperti dengan varargs. Pendekatan ini akan lebih baik jika Anda dapat menggunakan anotasi dan pembuatan kode untuk membuat kelas Opsi.
Java sekarang mendukung opsi dalam 1.8, saya terjebak dengan pemrograman di android jadi saya menggunakan nulls sampai saya bisa memperbaiki kode untuk menggunakan tipe opsional.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Argumen default tidak dapat digunakan di Jawa. Di mana dalam C #, C ++ dan Python, kita bisa menggunakannya ..
Di Java, kita harus menggunakan 2 metode (fungsi) alih-alih satu dengan parameter default.
Contoh:
Stash(int size);
Stash(int size, int initQuantity);
Ini adalah pertanyaan lama mungkin bahkan sebelum tipe Opsional yang sebenarnya diperkenalkan tetapi hari ini Anda dapat mempertimbangkan beberapa hal: - menggunakan metode overloading - menggunakan tipe Opsional yang memiliki keuntungan menghindari lewat NULL di sekitar tipe Opsional diperkenalkan di Jawa 8 sebelum biasanya digunakan dari lib pihak ketiga seperti Google's Guava. Menggunakan opsional sebagai parameter / argumen dapat dianggap sebagai penggunaan berlebihan karena tujuan utamanya adalah menggunakannya sebagai waktu pengembalian.
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Kita dapat membuat parameter opsional dengan Metode overloading atau Menggunakan DataType ...
| * | Metode kelebihan beban:
RetDataType NameFnc(int NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(String NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2)
{
// |* Code Todo *|
return RetVar;
}
Cara termudah adalah
| * | DataType ... bisa menjadi parameter opsional
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... serius? Apakah RetDataType
terlalu sulit untuk mengetik?
Jika Anda berencana untuk menggunakan antarmuka dengan beberapa parameter , seseorang dapat menggunakan pola struktural berikut dan menerapkan atau mengganti berlaku - metode yang didasarkan pada kebutuhan Anda .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Jika titik akhir API, cara yang elegan adalah dengan menggunakan anotasi "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Perhatikan dalam hal ini bahwa innerFunc akan memerlukan variabel, dan karena itu bukan titik akhir api, tidak dapat menggunakan anotasi Spring ini untuk menjadikannya opsional. Referensi: https://www.baeldung.com/spring-request-param