Est-il possible d'appeler un constructeur depuis un autre (dans la même classe, pas depuis une sous-classe)? Si oui comment? Et quel pourrait être le meilleur moyen d'appeler un autre constructeur (s'il existe plusieurs façons de le faire)?
Oui c'est possible:
public class Foo {
private int x;
public Foo() {
this(1);
}
public Foo(int x) {
this.x = x;
}
}
Pour chaîner à un constructeur de superclasse particulier au lieu d'un constructeur de la même classe, utilisez super
à la place de this
. Notez que vous ne pouvez chaîner qu’à un seul constructeur , et doit être la première instruction de votre corps de constructeur .
Voir aussi cette question connexe , qui concerne C # mais où les mêmes principes s'appliquent.
Utiliser this(args)
. Le modèle préféré consiste à travailler du plus petit constructeur au plus grand.
public class Cons {
public Cons() {
// A no arguments constructor that sends default values to the largest
this(madeUpArg1Value,madeUpArg2Value,madeUpArg3Value);
}
public Cons(int arg1, int arg2) {
// An example of a partial constructor that uses the passed in arguments
// and sends a hidden default value to the largest
this(arg1,arg2, madeUpArg3Value);
}
// Largest constructor that does the work
public Cons(int arg1, int arg2, int arg3) {
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
}
Vous pouvez également utiliser une approche plus récemment préconisée de valueOf ou simplement "de":
public class Cons {
public static Cons newCons(int arg1,...) {
// This function is commonly called valueOf, like Integer.valueOf(..)
// More recently called "of", like EnumSet.of(..)
Cons c = new Cons(...);
c.setArg1(....);
return c;
}
}
Pour appeler une super classe, utilisez super(someValue)
. L'appel à super doit être le premier appel du constructeur, sinon vous obtiendrez une erreur du compilateur.
[Remarque: je veux juste ajouter un aspect, que je n'ai pas vu dans les autres réponses: comment surmonter les limitations de l'exigence selon laquelle this () doit être sur la première ligne).]
Dans Java, un autre constructeur de la même classe peut être appelé depuis un constructeur via this()
. Notez cependant que this
doit être sur la première ligne.
public class MyClass {
public MyClass(double argument1, double argument2) {
this(argument1, argument2, 0.0);
}
public MyClass(double argument1, double argument2, double argument3) {
this.argument1 = argument1;
this.argument2 = argument2;
this.argument3 = argument3;
}
}
Le fait que this
doive apparaître sur la première ligne semble être une grosse limitation, mais vous pouvez construire les arguments d'autres constructeurs via des méthodes statiques. Par exemple:
public class MyClass {
public MyClass(double argument1, double argument2) {
this(argument1, argument2, getDefaultArg3(argument1, argument2));
}
public MyClass(double argument1, double argument2, double argument3) {
this.argument1 = argument1;
this.argument2 = argument2;
this.argument3 = argument3;
}
private static double getDefaultArg3(double argument1, double argument2) {
double argument3 = 0;
// Calculate argument3 here if you like.
return argument3;
}
}
Lorsque j'ai besoin d'appeler un autre constructeur à l'intérieur du code (pas sur la première ligne), j'utilise généralement une méthode d'assistance comme celle-ci:
class MyClass {
int field;
MyClass() {
init(0);
}
MyClass(int value) {
if (value<0) {
init(0);
}
else {
init(value);
}
}
void init(int x) {
field = x;
}
}
Mais le plus souvent, j'essaie de faire l'inverse en appelant les constructeurs les plus complexes, des plus simples à la première ligne, dans la mesure du possible. Pour l'exemple ci-dessus
class MyClass {
int field;
MyClass(int value) {
if (value<0)
field = 0;
else
field = value;
}
MyClass() {
this(0);
}
}
Dans un constructeur, vous pouvez utiliser le mot clé this
pour appeler un autre constructeur de la même classe. Cela s'appelle un appel de constructeur explicite.
Voici une autre classe Rectangle, avec une implémentation différente de celle de la section Objets.
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(1, 1);
}
public Rectangle(int width, int height) {
this( 0,0,width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
Cette classe contient un ensemble de constructeurs. Chaque constructeur initialise tout ou partie des variables membres du rectangle.
Comme tout le monde l’a déjà dit, vous utilisez this(…)
, appelé invocation de constructeur explicite .
Cependant, gardez à l'esprit que dans une telle instruction d'invocation de constructeur explicite vous ne pouvez pas vous en référer
this
ousuper
.Comme indiqué dans JLS (§8.8.7.1).
Oui, il est possible d'appeler un constructeur d'un autre. Mais il y a une règle à cela. Si un appel est passé d’un constructeur à un autre, alors
ce nouvel appel de constructeur doit être la première instruction du constructeur actuel
public class Product {
private int productId;
private String productName;
private double productPrice;
private String category;
public Product(int id, String name) {
this(id,name,1.0);
}
public Product(int id, String name, double price) {
this(id,name,price,"DEFAULT");
}
public Product(int id,String name,double price, String category){
this.productId=id;
this.productName=name;
this.productPrice=price;
this.category=category;
}
}
Donc, quelque chose comme ci-dessous ne fonctionnera pas.
public Product(int id, String name, double price) {
System.out.println("Calling constructor with price");
this(id,name,price,"DEFAULT");
}
De même, en cas d'héritage, lorsque l'objet de la sous-classe est créé, le constructeur de la super-classe est d'abord appelé.
public class SuperClass {
public SuperClass() {
System.out.println("Inside super class constructor");
}
}
public class SubClass extends SuperClass {
public SubClass () {
//Even if we do not add, Java adds the call to super class's constructor like
// super();
System.out.println("Inside sub class constructor");
}
}
Ainsi, dans ce cas, un autre appel de constructeur est d'abord déclaré avant toute autre instruction.
Oui, un nombre quelconque de constructeurs peuvent être présents dans une classe et ils peuvent être appelés par un autre constructeur à l'aide de this()
[Veuillez ne pas confondre this()
appel du constructeur avec this
mot clé]. this()
ou this(args)
devrait être la première ligne du constructeur.
Exemple:
Class Test {
Test() {
this(10); // calls the constructor with integer args, Test(int a)
}
Test(int a) {
this(10.5); // call the constructor with double arg, Test(double a)
}
Test(double a) {
System.out.println("I am a double arg constructor");
}
}
Ceci est connu sous le nom de surcharge du constructeur.
Veuillez noter que pour le constructeur, seul le concept de surcharge est applicable et non l'héritage ou le dépassement.
Je vais vous dire un moyen facile
Il existe deux types de constructeurs:
Je vais expliquer dans un exemple
class ConstructorDemo
{
ConstructorDemo()//Default Constructor
{
System.out.println("D.constructor ");
}
ConstructorDemo(int k)//Parameterized constructor
{
this();//-------------(1)
System.out.println("P.Constructor ="+k);
}
public static void main(String[] args)
{
//this(); error because "must be first statement in constructor
new ConstructorDemo();//-------(2)
ConstructorDemo g=new ConstructorDemo(3);---(3)
}
}
Dans l'exemple ci-dessus, j'ai montré 3 types d'appels
Remarque: il doit s'agir de la première instruction du constructeur.
Vous pouvez utiliser un constructeur d'un autre constructeur de la même classe en utilisant le mot clé "this". Exemple -
class This1
{
This1()
{
this("Hello");
System.out.println("Default constructor..");
}
This1(int a)
{
this();
System.out.println("int as arg constructor..");
}
This1(String s)
{
System.out.println("string as arg constructor..");
}
public static void main(String args[])
{
new This1(100);
}
}
Sortie - chaîne en tant que constructeur arg .. Constructeur par défaut .. int en tant que constructeur arg ..
Assez simple
public class SomeClass{
private int number;
private String someString;
public SomeClass(){
number = 0;
someString = new String();
}
public SomeClass(int number){
this(); //set the class to 0
this.setNumber(number);
}
public SomeClass(int number, String someString){
this(number); //call public SomeClass( int number )
this.setString(someString);
}
public void setNumber(int number){
this.number = number;
}
public void setString(String someString){
this.someString = someString;
}
//.... add some accessors
}
maintenant voici un petit crédit supplémentaire:
public SomeOtherClass extends SomeClass {
public SomeOtherClass(int number, String someString){
super(number, someString); //calls public SomeClass(int number, String someString)
}
//.... Some other code.
}
J'espère que cela t'aides.
Appel du constructeur depuis un autre constructeur
class MyConstructorDemo extends ConstructorDemo
{
MyConstructorDemo()
{
this("calling another constructor");
}
MyConstructorDemo(String arg)
{
System.out.print("This is passed String by another constructor :"+arg);
}
}
Vous pouvez aussi appeler le constructeur parent en utilisant super()
call
Oui, il est possible d'appeler un constructeur d'un autre en utilisant this()
class Example{
private int a = 1;
Example(){
this(5); //here another constructor called based on constructor argument
System.out.println("number a is "+a);
}
Example(int b){
System.out.println("number b is "+b);
}
Le mot clé this peut être utilisé pour appeler un constructeur à partir d'un constructeur, lors de l'écriture de plusieurs constructeurs pour un classe, il peut arriver que vous souhaitiez appeler un constructeur d’un autre pour éviter le code en double.
Ci-dessous un lien qui explique d'autres sujets sur constructeur et getters () et setters () et j'ai utilisé une classe avec deux constructeurs. J'espère que les explications et les exemples vous aideront.
Il existe des modèles de conception qui couvrent le besoin de construction complexe - si cela ne peut pas être fait de manière succincte, créez une méthode ou une classe d'usine.
Avec le dernier Java et l'ajout de lambdas, il est facile de créer un constructeur pouvant accepter le code d'initialisation souhaité.
class LambdaInitedClass {
public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
init.accept(this);
}
}
Appelez ça avec ...
new LambdaInitedClass(l -> { // init l any way you want });
C'est ce qu'on appelle l'anti-dessin ou l'enchaînement des constructeurs du constructeur télescopique. Oui, vous pouvez certainement faire. Je vois beaucoup d'exemples ci-dessus et je veux ajouter en disant que si vous savez que vous n'avez besoin que de deux ou trois constructeurs, cela pourrait aller. Mais si vous avez besoin de plus, essayez d’utiliser un modèle différent, tel que le modèle Builder. Comme par exemple:
public Omar(){};
public Omar(a){};
public Omar(a,b){};
public Omar(a,b,c){};
public Omar(a,b,c,d){};
...
Vous aurez peut-être besoin de plus. Le motif constructeur serait une excellente solution dans ce cas. Voici un article, il pourrait être utile https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti -pattern-60a33de7522e
Je sais qu'il y a tellement d'exemples de cette question mais ce que j'ai trouvé, je le mets ici pour partager mon idée. il y a deux façons de chaîner le constructeur. Dans la même classe, vous pouvez utiliser ce mot clé. En héritage, vous devez utiliser le mot-clé super.
import Java.util.*;
import Java.lang.*;
class Test
{
public static void main(String args[])
{
Dog d = new Dog(); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
Dog cs = new Dog("Bite"); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
// You need to Explicitly tell the Java compiler to use Argument constructor so you need to use "super" key Word
System.out.println("------------------------------");
Cat c = new Cat();
Cat caty = new Cat("10");
System.out.println("------------------------------");
// Self s = new Self();
Self ss = new Self("self");
}
}
class Animal
{
String i;
public Animal()
{
i = "10";
System.out.println("Animal Constructor :" +i);
}
public Animal(String h)
{
i = "20";
System.out.println("Animal Constructor Habit :"+ i);
}
}
class Dog extends Animal
{
public Dog()
{
System.out.println("Dog Constructor");
}
public Dog(String h)
{
System.out.println("Dog Constructor with habit");
}
}
class Cat extends Animal
{
public Cat()
{
System.out.println("Cat Constructor");
}
public Cat(String i)
{
super(i); // Calling Super Class Paremetrize Constructor.
System.out.println("Cat Constructor with habit");
}
}
class Self
{
public Self()
{
System.out.println("Self Constructor");
}
public Self(String h)
{
this(); // Explicitly calling 0 args constructor.
System.out.println("Slef Constructor with value");
}
}
Vous pouvez appeler un autre constructeur à l'aide du mot clé this(...)
(lorsque vous devez appeler un constructeur de la même classe) ou du mot clé super(...)
(lorsque vous devez appeler un constructeur à partir d'un superclasse).
Cependant, un tel appel doit être la première déclaration de votre constructeur. Pour surmonter cette limitation, utilisez cette réponse .
À l'origine d'un anser de Mirko Klemm, légèrement modifié pour répondre à la question:
Juste pour être complet: Il y a aussi le bloc d'initialisation de l'instance qui est exécuté toujours et avant l'appel de tout autre constructeur. Cela consiste simplement en un bloc d'instructions "{...}" quelque part dans le corps de votre définition de classe. Vous pouvez même en avoir plus d'un. Vous ne pouvez pas les appeler, mais ils s'apparentent à du "code de constructeur partagé" si vous souhaitez réutiliser du code sur des constructeurs, comme les méthodes d'appel.
Donc dans ton cas
{
System.out.println("this is shared constructor code executed before the constructor");
field1 = 3;
}
Il existe également une version "statique" de cette commande pour initialiser les membres statiques: "static {...}"
Je préfère cette façon:
class User {
private long id;
private String username;
private int imageRes;
public User() {
init(defaultID,defaultUsername,defaultRes);
}
public User(String username) {
init(defaultID,username, defaultRes());
}
public User(String username, int imageRes) {
init(defaultID,username, imageRes);
}
public User(long id, String username, int imageRes) {
init(id,username, imageRes);
}
private void init(long id, String username, int imageRes) {
this.id=id;
this.username = username;
this.imageRes = imageRes;
}
}
Oui, vous pouvez appeler des constructeurs depuis un autre constructeur. Par exemple:
public class Animal {
private int animalType;
public Animal() {
this(1);
}
public Animal(String animalType) {
this.animalType = animalType;
}
}
vous pouvez également lire les détails de Chaînage de constructeurs en Java