Yanıtlar:
varargs bunu yapabilir (bir şekilde). Bunun dışında, yöntemin bildirimindeki tüm değişkenler sağlanmalıdır. Bir değişkenin isteğe bağlı olmasını istiyorsanız, parametreyi gerektirmeyen bir imza kullanarak yöntemi aşırı yükleyebilirsiniz.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Java'da isteğe bağlı parametreleri simüle etmenin birkaç yolu vardır:
Yöntem aşırı yükleme.
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");
Bu yaklaşımın sınırlamalarından biri, aynı tipte iki isteğe bağlı parametreniz varsa ve bunlardan herhangi biri atlanabilirse işe yaramayacağıdır.
Varargs.
a) İsteğe bağlı tüm parametreler aynı tiptedir:
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) İsteğe bağlı parametre türleri farklı olabilir:
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");
Bu yaklaşımın ana dezavantajı, isteğe bağlı parametreler farklı tipteyse statik tip kontrolünü kaybetmenizdir. Ayrıca, her bir parametrenin farklı bir anlamı varsa, bunları ayırt etmek için bir yol gerekir.
Boşlara. Önceki yaklaşımların sınırlamalarını gidermek için null değerlere izin verebilir ve ardından bir yöntem gövdesindeki her parametreyi analiz edebilirsiniz:
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
Şimdi tüm bağımsız değişken değerleri sağlanmalıdır, ancak varsayılan değerler boş olabilir.
İsteğe bağlı sınıf. Bu yaklaşım null değerlerine benzer, ancak varsayılan değeri olan parametreler için Java 8 Optional sınıfını kullanır:
void foo(String a, Optional<Integer> bOpt) {
Integer b = bOpt.isPresent() ? bOpt.get() : 0;
//...
}
foo("a", Optional.of(2));
foo("a", Optional.<Integer>absent());
İsteğe bağlı bir yöntem sözleşmesini bir arayan için açık hale getirir, ancak böyle bir imza çok ayrıntılı bulabilir.
Güncelleme: Java 8, sınıftan java.util.Optional
çıkar çıkmaz sınıfı içerir, bu nedenle Java 8'de bu nedenle guava kullanmaya gerek yoktur. Yöntem adı biraz farklıdır.
Oluşturucu desen. Oluşturucu deseni yapıcılar için kullanılır ve ayrı bir Builder sınıfı eklenerek uygulanır:
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();
Haritalar. Parametre sayısı çok fazla olduğunda ve varsayılan değerlerin çoğu için genellikle kullanıldığında, yöntem bağımsız değişkenlerini adlarının / değerlerinin haritası olarak iletebilirsiniz:
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"));
Java 9'da bu yaklaşım daha kolay hale geldi:
@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"));
İstenilen bir sonuç elde etmek için bu yaklaşımlardan herhangi birini birleştirebileceğinizi lütfen unutmayın.
a
Değişkeniniz bir String olmasına rağmen (Cast doğrudur) bir Tamsayı için yazım denetimi yapıyorsunuz .
Java 5.0 ile isteğe bağlı parametreler vardır. Sadece işlevinizi böyle ilan edin:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
doSomething();
veya doSomething(true);
şimdi arayabilirsin .
doSomething() { doSomething(true); }
Bunun gibi bir şey kullanabilirsiniz:
public void addError(String path, String key, Object... params) {
}
params
Değişken isteğe bağlıdır. Null olabilecek bir Nesne dizisi olarak ele alınır.
Garip bir şekilde, belgelerde bu konuda hiçbir şey bulamadım, ama işe yarıyor!
Bu, Java 1.5 ve sonraki sürümlerde "yeni" dir (Java 1.4 veya önceki sürümlerde desteklenmez).
Kullanıcı bhoot'un aşağıda da belirttiğini görüyorum.
Ne yazık ki Java varsayılan parametreleri doğrudan desteklemiyor.
Ancak, bir dizi JavaBean ek açıklaması yazdım ve bunlardan biri aşağıdaki gibi varsayılan parametreleri destekliyor:
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);
}
Ek açıklama işlemcisi, bunu doğru şekilde desteklemek için yöntem aşırı yükleri oluşturur.
Bkz. Http://code.google.com/p/javadude/wiki/Annotations
Http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample adresindeki tam örnek
VarArgs ve aşırı yüklemeden bahsedilmiştir. Başka bir seçenek, aşağıdaki gibi görünen bir Oluşturucu kalıbıdır:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Her ne kadar bu model bir kurucuda isteğe bağlı parametrelere ihtiyacınız olduğunda en uygun olur.
JDK> 1.5 sürümünde bu şekilde kullanabilirsiniz;
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);
}
}
}
Böyle bir yöntem aşırı yükleme kullanarak bir şey yapabilirsiniz.
public void load(String name){ }
public void load(String name,int age){}
Ayrıca @Nullable ek açıklamasını da kullanabilirsiniz
public void load(@Nullable String name,int age){}
ilk parametre olarak null değerini iletmeniz yeterlidir.
Aynı tip değişkenini geçiyorsanız bunu kullanabilirsiniz
public void load(String name...){}
Aşırı yükleme iyidir, ancak varsayılan değere ihtiyaç duyan çok sayıda değişken varsa, aşağıdakilerle karşılaşırsınız:
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) { }
Bu yüzden Java tarafından sağlanan Değişken Bağımsız Değişken'i kullanmanızı öneririm. İşte açıklama için bir link .
Bunun gibi isteğe bağlı değerlerinizi içermek için oluşturucuya çok benzer bir sınıf kullanabilirsiniz.
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);
}
Gibi kullanın
foo(o -> o.setSomeString("something").setSomeInt(5));
Çıktı
someString = something, someInt = 5
Gibi çağırmanız gereken tüm isteğe bağlı değerleri atlamak için foo(o -> {});
veya isterseniz foo()
, isteğe bağlı parametreleri almayan ikinci bir yöntem oluşturabilirsiniz .
Bu yaklaşımı kullanarak, herhangi bir belirsizlik olmadan herhangi bir sırada isteğe bağlı değerler belirtebilirsiniz. Ayrıca varargs'ın aksine farklı sınıfların parametrelerine sahip olabilirsiniz. Options sınıfını oluşturmak için ek açıklamaları ve kod oluşturmayı kullanabiliyorsanız bu yaklaşım daha da iyi olacaktır.
Java artık 1.8'de opsiyonel desteği destekliyor, isteğe bağlı türleri kullanmak için kodu yeniden düzenleyene kadar null kullanıyorum.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Varsayılan bağımsız değişkenler Java'da kullanılamaz. C #, C ++ ve Python'da nerede kullanabiliriz ..
Java'da, varsayılan parametreleri olan biri yerine 2 yöntem (işlev) kullanmamız gerekir.
Misal:
Stash(int size);
Stash(int size, int initQuantity);
Bu, gerçek Opsiyonel tip tanıtılmadan önce bile eski bir sorudur, ancak bu günlerde birkaç şey düşünebilirsiniz: - yöntem aşırı yüklemesi kullanın - kullanım NULL'ların etrafından geçmekten kaçınma avantajına sahip isteğe bağlı tip Opsiyonel tip genellikle kullanılmadan önce Java 8'de tanıtıldı Google'ın Guava gibi üçüncü taraf lib'lerinden. İsteğe bağlı olarak parametre / argüman olarak kullanmak, asıl amaç bir dönüş süresi olarak kullanmak olduğu için aşırı kullanım olarak düşünülebilir.
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Yöntem aşırı yükleme veya DataType kullanarak isteğe bağlı parametre yapabilirsiniz ...
| * | Yöntem aşırı yükleme:
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;
}
En kolay yol
| * | DataType ... isteğe bağlı parametre olabilir
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... ciddi anlamda? Yazmak RetDataType
çok zor mu?
Birden fazla parametreli bir arayüz kullanmayı planlıyorsanız , aşağıdaki yapısal desen kullanılabilir ve gereksiniminize göre bir yöntem uygulayabilir veya geçersiz kılınabilir .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Bir API uç noktasıysa, "Bahar" ek açıklamalarını kullanmanın zarif bir yolu:
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Bu durumda innerFunc değişkene ihtiyaç duyacaktır ve api uç noktası olmadığından, bu Bahar ek açıklamasını isteğe bağlı yapmak için kullanamazsınız. Referans: https://www.baeldung.com/spring-request-param