Contacts

Java constructors. Why are constructors needed? The concept of a default constructor

1. The concept of a default constructor

A default constructor is a constructor that takes no parameters. A default constructor can be declared explicitly in a class or generated automatically.

In the most general case, for the class ClassName , the default constructor looks like this:

class ClassName(... // constructor declaration ClassName() ( // constructor body // ... } ... }
2. In which cases is the default constructor automatically generated in the class and in which not? Example

If no constructor is declared in the class, then a default constructor will be generated. That is, a default constructor is automatically generated in a class only if the class does not contain implementations of other constructors. If a class contains an implementation of at least one constructor with parameters, then in order to declare a default constructor, it must be declared explicitly in the class.

For example. In the following class declaration, a default constructor is automatically generated

class CMyClass( int d; int GetD() ( return d; ) void SetD( int nd) ( d = nd; ) )

The above code means that you can declare a class object using the default constructor:

// works because the class no longer implements any constructor CMyClass mc = new CMyClass();

If at least one other constructor is added to the body of the CMyClass class (for example, a constructor with one parameter), then the default constructor will not be automatically generated

class CMyClass( int d; // default constructor is no longer automatically generated CMyClass( int nd) ( d = nd; ) int GetD() ( return d; ) void Set( int nd) ( d = nd; ) )

After the implementation above, declaring an object using a default constructor will fail. However, it is possible to declare an object using a constructor with one parameter

// compilation error because another constructor is already declared in the class // CMyClass mc = new CMyClass(); CMyClass mc2= new CMyClass(7); // and this code works

The above line will result in a compilation error:

The constructor CMyClass() is undefined

In order to have a default constructor implementation and declare a class object using a default constructor, it must be explicitly set. It could be, for example, as follows

class CMyClass( int d; // explicit default constructor declaration CMyClass() ( d = 0; ) // constructor declaration with 1 parameter, CMyClass( int nd) ( d = nd; ) int GetD() ( return d; ) void Set( int nd) ( d = nd; ) )

After such an implementation, you can create an instance of the class using two constructors, for example

CMyClass mc = new CMyClass(); // the default constructor is called mc.d = 25; CMyClass mc2= new CMyClass(5); // the constructor with 1 parameter is called

3. Calling constructors from other constructors. Example

The Java programming language allows you to call class constructors from another constructor of the same class. For this, the this keyword is used, which is a reference to the current class.

Example. The example demonstrates the use of the CPixel class, which implements a pixel on a monitor screen.

// Class that implements a pixel on the monitor screen public class CPixel( // internal class variables private int x, y; // pixel coordinates private int color; // pixel color // constructor without parameters (default constructor) CPixel() ( x = y = color = 0; ) // constructor with 2 parameters that only initialize coordinates CPixel( int _x, int _y) ( x = _x; y = _y; color = 0; ) // constructor with 1 parameter that only initializes the color CPixel( int _color) ( color = _color; x = y = 0; ) // 3-parameter constructor that calls the 2-parameter constructor CPixel( int _x, int _y, int _color) ( // call constructor with 2 parameters: mandatory first operation and only once this(_x, _y); //this(_color); // repeated call of the constructor is prohibited this.color = _color; // so it is possible ) // access methods int GetX() ( return x; ) int GetY() ( return y; ) int GetColor() ( return color; ) )

Using the CPixel class in another program code (method)

CPixel cp1= new CPixel(2,8); // call constructor with 2 parameters CPixel cp2= new CPixel(3,5,8); // call a constructor that will call another constructor int d; d = cp1.GetX(); // d = 2 d = cp2.GetColor(); // d = 8 d = cp2.GetY(); // d = 5 ...

4. What restrictions (requirements) are imposed on calling other constructors from a class constructor?

To correctly call other constructors from a class constructor, the following requirements (restrictions) must be adhered to:

  • only one other class constructor can be called. Calling two or more other constructors of this class is prohibited. This follows from the logic that a class constructor is designed to create a class object only once (and not twice or more);
  • calling another constructor must be the first operation in the calling constructor. If in the calling constructor the call of another constructor is implemented by the second (third, etc.) operation, the compiler will generate an error.

Method in Java is a set of expressions, the totality of which allows you to perform a certain operation. So, for example, when the System.out.println() method is called, the system executes a series of commands to print a message to the console.

In this step, you will learn how to create your own methods with or without return values, call methods with or without parameters, and isolate methods when developing a program.

Create a method

Below is an example illustrating the syntax of a method, how to create a method in Java.

Syntax

public static int methodName(int a, int b) ( // body )
  • public static - modifier;
  • int - return type;
  • methodName - method name;
  • a, b - formal parameters;
  • int a, int b - list of parameters.

The definition of a method is represented by the header and body of the method. We can observe the same thing in the following method creation syntax.

Syntax

modifier returnType nameOfMethod (Parameter List) ( // method body )

The above syntax includes:

  • modifier - determines the type of access for the method and the possibility of its use.
  • returnType - the method can return a value.
  • nameOfMethod - Specifies the name of the method. The signature of a method includes the name of the method and a list of parameters.
  • Parameter List - the list of parameters is represented by the type, order and number of method parameters. This option is set arbitrarily; a null parameter may be present in the method.
  • method body - the method body defines the method of working with commands.

Example

/* code snippet returns the minimum between two numbers */ public static int minFunction(int n1, int n2) ( int min; if (n1 > n2) min = n2; else min = n1; return min; )

Method call

Before using a method, it must be called. There are two ways to call a method in Java i.e. the method produces a return value or does not produce (there is no return value).

The method call algorithm is quite simple. When a program calls a method in Java, programmatic control is transferred to the called method. This called method then returns control to the calling client in two cases, if:

  • a return statement is executed;
  • the closing curly brace of the end of the method has been reached.

The void return method invokes the command. Consider an example:

System.out.!");

The value return method can be illustrated with the following example:

int result = sum(6, 9);

The example below demonstrates how to define and call a method in Java.

Example

public class ExampleMinNumber ( public static void main(String args) ( int a = 11; int b = 6; int c = minFunction(a, b); System.out.println("Min value = " + c); ) / * Returns the minimum of two numbers */ public static int minFunction(int n1, int n2) ( int min; if (n1 >

Minimum value = 6

The void keyword

The void keyword in Java allows us to create methods that do not return a value. In the example below, we have considered a method of the void type - methodRankPoints. Java void methods do not return any value. Calling a void type method is performed by a command, i.e. methodRankPoints(255.7);. This is a java expression that ends with a semicolon, as shown in the example below:

Example

public class ExampleVoid ( public static void main(String args) ( methodRankPoints(255.7); ) public static void methodRankPoints(double points) ( if (points >= 202.5) ( System.out.println("Rank A1"); )else if (points >= 122.4) ( System.out.println("Rank A2"); )else ( System.out.println("Rank A3"); ) ) )

As a result, the following result will be obtained:

Rank A1

Passing parameters by value in Java

When the calling process executes, Java passes arguments. The procedure must be carried out in the order specified by the corresponding parameters in the method specification. Parameters can be passed by value or by reference.

In Java, passing parameters by value means calling a method with a parameter. Due to this, the value of the argument is passed to the parameter.

Example

The following program shows an example of passing a parameter by value. The argument values ​​remain unchanged even after the method is called.

Public class swappingExample ( public static void main(String args) ( int a = 30; int b = 45; System.out.println("Before passing, the values ​​of the arguments a = " + a + " and b = " + b ); // Calling the transfer method swapFunction(a, b); System.out.println("\nNow, before and after passing the value of the arguments "); System.out.println("remained unchanged, a = " + a + " and b = " + b); ) public static void swapFunction(int a, int b) ( System. out. println("Before swapping: a = " + a + " b = " + b); // Passing int parameters c = a; a = b; b = c; System.out.println("After replacement: a = " + a + " b = " + b); ) )

We get the following result:

Before passing, the values ​​of the arguments a = 30 and b = 45 Before replacing: a = 30 b = 45 After replacing: a = 45 b = 30 Now, before and after passing, the values ​​of the arguments remained unchanged, a = 30 and b = 45

Method Overloading

Method Overloading in Java- the case when there are two or more methods in the class with the same name, but different parameters. This process is different from overriding methods. When methods are overridden, the method is characterized by the same name, type, number of parameters, and so on.

Consider the example that was presented above when defining the minimum numbers of an integer type. So let's say we want to define the minimum number of a double type. In this case, the concept of overloading will be introduced to create two or more methods with the same name but different parameters.

The above example illustrates the above.

Example

public class ExampleOverloading ( public static void main(String args) ( int a = 7; int b = 3; double c = 5.1; double d = 7.2; int result1 = minFunction(a, b); // same function with others parameters double result2 = minFunction(c, d); System.out.println("Minimum value = " + result1); System.out.println("Minimum value = " + result2); ) // for integer public static int minFunction (int n1, int n2) ( int min; if (n1 > n2) min = n2; else min = n1; return min; ) // for double public static double minFunction(double n1, double n2) ( double min; if (n1 > n2) min = n2; else min = n1; return min; ) )

As a result, the following result will be obtained:

Minimum value = 3 Minimum value = 5.1

Overloading methods make a program readable. So there are two methods with the same name but different parameters. As a result, we got the minimum int number and double type number.

Using Command Line Arguments

During the program, you may need to transfer certain information. This can be done in Java by passing command line arguments to main().

In Java, a command line argument represents the information that immediately follows the name of a program on the command line when it is executed. Getting access to command line arguments in a java program is not difficult. They are stored as a string in the string array passed to main().

Example

The program below displays all command line arguments invoked.

Public class CommandLine ( public static void main(String args) ( for(int i = 0; i

Try running this program as shown below:

$java CommandLine is command line 300 -200

As a result, the following result will be obtained:

args: this is args: command line args: string args: 300 args: -200

Constructor in Java

In Java constructor initializes an object when it is created. Its name is similar to the class name, and its syntax is similar to that of a method. However, unlike the latter, the constructor does not have a return value.

Typically, a constructor in Java can be used to set an initial value to instance variables defined by a class, or to perform any other startup procedures necessary to create a fully formed object.

Constructors are present in all classes, regardless of how they are specified, because Java automatically provides a default constructor that initializes all class member variables to zero. However, once you define your own constructor, the default constructor will no longer be used.

Example

The example below shows the use of a class constructor without parameters.

// Simple constructor. class MyClass ( int x; // Next comes the constructor MyClass() ( x = 10; ) )

To initialize objects, you need to make a constructor call as in the following example.

Public class ConsDemo ( public static void main(String args) ( MyClass t1 = new MyClass(); MyClass t2 = new MyClass(); System.out.println(t1.x + " " + t2.x); ) )

We get the result:

Parameterized constructor

Most often, you will need a constructor that takes one or more parameters. Adding parameters to a constructor is the same as adding them to a method, you just need to put them in parentheses after the constructor name.

Example

// Simple constructor. class MyClass ( int x; // Below constructor MyClass(int i) ( x = i; ) )

In order to initialize objects, you will need to call the constructor as in the following example.

Public class ConsDemo ( public static void main(String args) ( MyClass t1 = new MyClass(10); MyClass t2 = new MyClass(20); System.out.println(t1.x + " " + t2.x); ) )

We get the following result:

keyword this

keyword this- is used to refer to the current class given an instance method or constructor. Using this in Java, you can refer to class instances such as constructors, variables, and methods.

Note: the this keyword is only used within instance methods or constructors.

Typically, the this keyword in Java is used to:

  • differentiation between instance variables and local variables if they have the same name, as part of a constructor or method.
class Student ( int age; Student(int age) ( this.age = age; ) )
  • calling a constructor of one type (parameterized constructor or default constructor) from another within a class. This process is also called explicit constructor invocation.
class Student ( int age Student() ( this(20); ) Student(int age) ( this.age = age; ) )

Example

Public class This_Example ( // Initialize the variable num int num = 11; This_Example() ( System. out. println("This is an example program with the keyword this"); ) This_Example(int num) ( // Call the default constructor this( ); // Assign local variable num to instance variable num this.num = num; ) public void greet() ( System.out.println("Hi! Welcome to ProgLang!"); ) public void print() ( // Local variable num int num = 20 // Call class method greet this.greet() // Print local variable System.out.println("Value of local variable num: " + num); // Print instance variable System .out.println("Instance variable value num: " + this.num); ) public static void main(String args) ( // Initialize This_Example class obj1 = new This_Example(); // Call print method obj1.print() ; // Passing the new value of the num variable through the parameterized constructor This_Example obj2 = new This_Example(30); // You calling the print method again obj2.print(); ) )

As a result, the following result will be obtained:

This is an example program with the this keyword Hello! Welcome to Proglang! Value of local variable num: 22 Value of instance variable num: 11 This is an example program with the this keyword Hello! Welcome to Proglang! Value of local variable num: 22 Value of instance variable num: 30

Variable Arguments (var-args)

JDK 1.5 and higher allows you to pass a variable number of arguments of the same type to a method. A parameter in a method is declared like this:

TypeName... parameterName

When declaring a method, you specify the type followed by an ellipsis (...). Only one variable length parameter can be specified in a method, and this parameter must be the last parameter. Any regular parameters must precede it.

Example

public class VarargsDemo ( public static void main(String args) ( // Call method with args variable printMax(27, 11, 11, 5, 77.1); printMax(new double(10, 11, 12, 77, 71)); ) public static void printMax(double... numbers) ( if (numbers.length == 0) ( System.out.println("No argument passed"); return; ) double result = numbers; for (int i = 1; i result) result = numbers[i]; System.out.println("Max value " + result); ) )

As a result, the following result will be obtained:

Maximum value 77.1 Maximum value 77.0

finalize() method

finalize() method- a method that will be called immediately before the final destruction of the object by the garbage collector. (finalizer). In Java, finalize() can be used to ensure clean completion of an object.

For example, we can use finalize() to make sure that an open file owned by a given object has been closed.

To add a finalizer to a class, you simply need to define a finalize() method in Java. The Java runtime environment calls this method just before processing an object of this class.

As part of the finalize() method, you specify the actions that must be performed before the object is destroyed.

In general, the finalize() method looks like this:

Protected void finalize() ( // code finalization here )

Here, the protected keyword represents a specifier that prevents finalize() from being accessed by code defined outside of its class.

This indicates that you cannot know how or even when finalize() will be executed. For example, if your program terminates before garbage collection, finalize() will not be executed.

A constructor is a special method that is called when a new object is created. It is not always convenient to initialize all class variables when creating an instance of it. Sometimes it's easier to have some values ​​created by default when the object is created. In fact, the constructor is needed for automatic initialization of variables.

A constructor initializes an object directly at creation time. The name of the constructor is the same as the name of the class, including case, and the syntax of a constructor is similar to that of a method without a return value.

Private int Cat(); // this is what the method called Cat looks like Cat(); // this is how the Cat class constructor looks like

Unlike a method, a constructor never returns anything.

A constructor defines the actions to be taken when an object of a class is created and is an important part of a class. As a rule, programmers try to explicitly specify a constructor. If there is no explicit constructor, then Java will automatically create one for default use. When we implemented the class box, then no constructor was created.

Let's add a constructor to the class that will simply set the initial values ​​for the box.

Class Box ( int width; // box width int height; // box height int depth; // box depth // Box() constructor ( width = 10; height = 10; depth = 10; ) // calculate box volume int getVolume() ( return width * height * depth; ) )

We have temporarily removed the method setDim() and added a constructor. Let's see what happens:

Box catBox = new Box(); mInfoTextView.setText("Box Volume: " + catBox.getVolume());

The program will output the volume of the box, even though we didn't specify any dimensions for it. Thanks to the constructor, any created box will have some fixed volume.

Naturally, you can return a method setDim()(see the article about classes) and set your own dimensions for the box:

Box catBox = new Box(); // set custom dimensions for the box catBox. setDim(10, 20, 30); mInfoTextView.setText("Box Volume: " + catBox.getVolume());

By now it should be clear to you that when after the keyword new we write the name of the class with brackets, then we are actually calling the class constructor.

The question arises - but at first, when creating the class, we did not create a constructor, however, the code newBox() worked. The fact is that if the constructor is not explicitly defined, then Java will create a constructor that will be used by default. In this case, it will simply assign zero values ​​to all variables. If you have created a constructor yourself, then the default constructor will not be used.

Like any method, a constructor can have arguments. Constructor arguments pass parameters to initialize the object. For example, if the class cat there is a constructor that takes as an argument an integer denoting the age of the cat, then the objects cat will be created like this:

Cat cat = new Cat(8); // cat is 8 years old

If a cat(int) is the only class constructor, the compiler will not allow objects to be created cat in some other way.

But back to the boxes for cats. The constructor we created is not particularly useful, as it creates the same boxes. Let's create a constructor with parameters in the class box and comment out the first parameterless constructor:

// Second constructor Box(int ​​w, int h, int d) ( width = w; height = h; depth = d; )

If the class contains one constructor with parameters, then you will have to specify the values ​​when declaring the class:

// This constructor is no longer valid // Box catBox = new Box(); // In the constructor, you need to specify the box size values ​​Box catBox = new Box(100, 200, 100); mInfoTextView.setText("Box Volume: " + catBox.getVolume());

By the way, with such a constructor, the method setDim() we don't need it anymore. We can set the dimensions of the box directly in the constructor. Since the box is most likely constant and does not change its size, the method is perhaps superfluous. But if we change the size of the box, then the method will have to be left.

A class can have multiple constructors. Uncomment the first constructor and create two boxes - a default box and a large box.

Box defaultBox = new Box(); mInfoTextView.setText("Standard box volume: " + defaultBox.getVolume()); Box bigBox = new Box(100, 200, 200); mInfoTextView.append("\nBig Box Volume: " + bigBox.getVolume());

That is, we see that constructors support overloading, as do methods.

For example, we can create another constructor specifically for a box in the form of a cube, where all sides are equal:

// Third constructor for the cube Box(int ​​len) ( width = height = depth = len; )

Calculate the size of the cube:

Box cube = new Box(5); intvol = cube.getVolume(); mInfoTextView.setText("Cube volume: " + vol);

Using an object as parameters

We have so far used simple types as parameters in constructors. But you can also pass an object of the class itself. Let's add another constructor:

// Use an object of type Box Box(Box ob) ( width = ob.width; height = ob.height; depth = ob.depth; )

In the code of the program, you can use the constructor as follows:

Box1 = new Box(100, 200, 100); Box cloneBox = new Box(box1); intvol = cloneBox.getVolume(); mInfoTextView.setText("Box volume: " + vol);

Box class (source)

package en.alexanderklimov.box; class Box ( int width; // width of the box int height; // height of the box int depth; // depth of the box // Constructor Box() ( width = 10; height = 10; depth = 10; ) // Second constructor Box( int w, int h, int d) ( width = w; height = h; depth = d; ) // Third constructor for the cube Box(int ​​len) ( width = height = depth = len; ) // Use an object of type Box Box(Box ob) ( width = ob.width; height = ob.height; depth = ob.depth; ) // calculate the volume of the box int getVolume() ( return width * height * depth; ) // set the dimensions of the box void setDim (int w, int h, int d) ( width = w; height = h; depth = d; ) )

Calling overloaded constructors via this()

When dealing with overloaded constructors, it is convenient to call one constructor from another via the keyword this. When executing the constructor this() the overloaded constructor that matches the parameter list is executed first. Then the statements inside the original constructor, if any, are executed. Constructor call this() must be the first statement in the constructor.

First, let's create a class that does not use a constructor. this() to understand the difference.

Class Cat ( int age; int birthday; // Initialize variables explicitly Cat(int i, int j) ( age = i; birthday = j; ) // Initialize variables with the same value Cat(int i) ( age = i; birthday = i; ) // Set the default values ​​to 0 Cat() ( age = 0; birthday = 0; ) )

We have created a class with three constructors. Rewrite the class using the constructor this().

Class Cat( int age; int birthday; // Initialize variables explicitly Cat(int i, int j) ( age = i; birthday = j; ) // Initialize variables with the same value Cat(int i) ( this(i, i); // calling Cat(i, i); ) // Set default values ​​to 0 Cat() ( this(0); // calling Cat(0); ) )

We now have only one constructor that assigns values ​​to fields - Cat(int, int). What happens when the statement is executed:

Cat cat = new Cat(8);

Constructor call cat(8) causes the constructor to be executed this(8, 8), which is equivalent to calling the constructor Cat(8, 8).

What happens when the statement is executed:

Cat cat2 = new Cat();

In this case, the constructor is called this(0), which causes the constructor to execute cat(0), since this is the version of the constructor that matches the list of parameters. At the same time, the constructor cat(0) essentially calls the constructor Cat(0, 0).

Using Overloaded Constructors Through a Constructor this() allows you to eliminate code duplication, reducing class loading time.

But be careful, because constructors that call a constructor this(), are slightly slower.

private constructor

Sometimes a class is created only to store some static fields and static methods. It is customary for such classes to be named utilities, but this is optional. Such a class does not need a constructor, but if the class author did not create one, then the system itself will create a default constructor. Such a constructor does not make sense and can also be a source of errors. To guard against this problem, you yourself must explicitly create an empty constructor and make it private.

public class Utils ( private Utils() ( throw new AssertionError(); ) ... //your correct code // Incorrect code, just for demonstration purposes! public static void someMethod()( Utils utils = new Utils(); utils. toString(); ) )

Line throw new AssertionError() is not required, but it will help catch the error if you call the constructor on the class itself. The compiler will skip this option, but the program will exit with an error.

Utils.someMethod(); // the program will close with an error

You cannot create a subclass for this class.

The fact is that:

1. If you create a class and define a constructor with arguments in it (class AClass, which has only one constructor that takes int i), then the compiler will no longer create a default constructor. Because that would break the contract of AClass, which cannot be initialized without arguments. If you also want to have a default constructor, set it explicitly now.

Otherwise, it would be impossible to prevent the creation of a default constructor, which would be bad.

2. When creating constructors of a class BClass that is inherited from another class, the compiler requires that the first line of the constructor be a call to another constructor (inherited or in this class).

Why? Because since you are deriving from a class, you want to reuse its logic. The constructor brings an instance of the class to some initial integral state. In your case, AClass requires an argument to initialize, without which the JVM does not know how to initialize an instance of the class.

If the class has no constructors defined, then it tries to create a default constructor, i.e. without arguments:

public class AClass1 ( )

Since no constructors are explicitly defined here AND the class is not inherited from other classes, the compiler generates a default constructor.

This is equivalent to this definition:

Public class AClass1 ( public AClass1() ( ) )

Now let's look at BClass1:

public class BClass1 extends AClass1 ( )

Here, too, constructors are not explicitly defined, and the compiler tries to create a default constructor. Since class AClass1 has a default constructor, it will create a default constructor which will call AClass1's constructor. This code is equivalent to this:

Public class BClass1 extends AClass1 ( public BClass1() ( super(); ) )

In your case, a class is created WITHOUT a default constructor:

Public AClass ( public AClass(int i) ( ) )

Since (at least one) constructor is declared here, the default constructor is no longer created. That is, such code will no longer compile:

AClass a = new AClass(); // does not work

need something like

AClass a = new AClass(1);

Accordingly, any BClass constructor will require a call to some AClass or BClass constructor. With this description, the compiler will swear:

Public BClass extends AClass()

Because there will be an attempt to call the default constructor of the AClass class, which is not defined:

Public BClass extends AClass ( public BClass() ( super(); // error; there is no such constructor in AClass ) )

However, it is possible to create a BClass with a default constructor by setting the AClass constructor to some value:

Public class BClass extends AClass ( public BClass() ( super(1); ) )

This will compile.

Hello! Today we will analyze a very important topic that concerns our objects. Here, without exaggeration, we can say that you will use this knowledge every day in real work! We'll talk about constructors.

You may have heard this term for the first time, but in fact you probably used constructors, only you didn’t notice it yourself :) We will see this later.

What are constructors and why are they needed?

Let's consider two examples. public class Car ( String model; int maxSpeed; public static void main (String args) ( Car bugatti = new Car () ; bugatti. model = "Bugatti Veyron" ; bugatti. maxSpeed ​​= 407 ; ) ) We created our car and installed for him model and maximum speed. However, in a real project, the Car object will obviously not have 2 fields. And, for example, 16 fields! public class Car ( String model; //model int maxSpeed; //max speed//engine volume//owner's last name//number of seats in the cabin String salonMaterial; // interior material boolean insurance; //is it insured//producing country inttrunkVolume; // trunk volume int accelerationTo100km; public static void main (String args) ( Car bugatti = new Car () ; bugatti. color = "blue" ; bugatti. accelerationTo100km = 3 ; bugatti. engineVolume = 6.3 ; bugatti. manufacturerCountry = "Italy" ; bugatti. ownerFirstName = " Amigo" ; bugatti. yearOfIssue = 2016 ; bugatti. insurance = true ; bugatti. price = 2000000 ; bugatti. isNew = false ; bugatti. placesInTheSalon = 2 ; bugatti. maxSpeed ​​= 407 ; bugatti. model = "Bugatti Veyron" ; ) ) We have created a new Car object. One problem: we have 16 fields, but we initialized only 12! Try now by code to find those that we forgot! Not so easy, right? In such a situation, the programmer can easily make a mistake and skip the initialization of some field. As a result, the behavior of the program will become erroneous: public class Car ( String model; //model int maxSpeed; //max speed int wheels; //disk width double engineVolume; //engine volume Stringcolor; //color int yearOfIssue; //year of issue String ownerFirstName; //owner name String ownerLastName; //owner's last name long price; //price boolean isNew; //new or not int placesInTheSalon; //number of seats in the cabin String salonMaterial; // interior material boolean insurance; //is it insured String manufacturerCountry; //producing country inttrunkVolume; // trunk volume int accelerationTo100km; //acceleration to 100 km/h in seconds public static void main (String args) ( Car bugatti = new Car () ; bugatti. color = "blue" ; bugatti. accelerationTo100km = 3 ; bugatti. engineVolume = 6.3 ; bugatti. manufacturerCountry = "Italy" ; bugatti. ownerFirstName = " Amigo" ; bugatti. yearOfIssue = 2016 ; bugatti. insurance = true ; bugatti. price = 2000000 ; bugatti. isNew = false ; bugatti. placesInTheSalon = 2 ; bugatti. maxSpeed ​​= 407 ; bugatti. model = "Bugatti Veyron" ; System. out.println( "Model Bugatti Veyron. Engine size - "+ bugatti. engineVolume + ", trunk - " + bugatti. trunkVolume+ ", salon is made of"+ bugatti. salonMaterial + ", disc width - "+ bugatti. wheels + ". Was acquired in 2018 by Mr. "+ bugatti. ownerLastName); ) ) Console output: Model Bugatti Veyron. Engine size - 6.3, trunk - 0, interior made of null, wheel width - 0. Was purchased in 2018 by Mr. null Your buyer who paid $2 million for a car will obviously not like being named “ mister null”! But seriously, as a result, our program ended up with an incorrectly created object - a car with a disk width of 0 (that is, no disks at all), a missing trunk, an interior made of an unknown material, and even belonging to someone who knows. One can only imagine how such an error can “shoot” when the program is running! We need to somehow avoid such situations. It is necessary that our program has a restriction: when creating a new machine object for it always must be specified, for example, model and maximum speed. Otherwise, do not allow object creation. This task is easily handled constructor functions. They got their name for a reason. The constructor creates a kind of "skeleton" of the class, which each new object of the class must correspond to. For convenience, let's go back to a simpler version of the Car class with two fields. Given our requirements, the constructor for the Car class will look like this: public Car (String model, int maxSpeed) ( this . model = model; this . maxSpeed ​​= maxSpeed; ) And the object creation now looks like this: public static void main (String args ) ( Car bugatti = new Car ("Bugatti Veyron" , 407 ) ; ) how constructor is created. It is similar to a regular method, but it does not have a return type. In this case, the name of the class is indicated in the constructor, also with a capital letter. In our case - Car . In addition, the constructor uses a new keyword for you this. "this" in English - "this one". This word refers to a specific subject. The code in the constructor: public Car (String model, int maxSpeed) ( this . model = model; this . maxSpeed ​​= maxSpeed; ) can be translated almost verbatim: " model for this car (which we are currently creating) = model argument, which is specified in constructor.maxSpeed ​​for this machine (which we are creating) = to the maxSpeed ​​argument given in the constructor." And so it happened: public class Car ( String model; int maxSpeed; public Car (String model, int maxSpeed) ( this . model = model; this . maxSpeed ​​= maxSpeed; ) public static void main (String args) ( Car bugatti = new Car ("Bugatti Veyron" , 407 ) ; System. out. println (bugatti. model) ; System. out. println (bugatti. maxSpeed) ; ) ) Console output: Bugatti Veyron 407 The constructor successfully assigned the desired values. You may have noticed that a constructor is very similar to a regular method! So it is: a constructor is a method, only a little specific :) Just like in a method, we passed parameters to our constructor. And just like calling a method, calling a constructor will fail if they are not specified: public class Car ( String model; int maxSpeed; public Car (String model, int maxSpeed) ( this . model = model; this . maxSpeed ​​= maxSpeed; ) public static void main (String args) ( Car bugatti = new Car () ; //error! ) ) See, the constructor did what we were trying to achieve. Now you can not create a car without speed or without a model! The similarities between constructors and methods don't end there. Just like methods, constructors can be overload. Imagine that you have 2 cats at home. You took one of them as a kitten, and you brought the second home from the street as an adult and you don’t know exactly how old he is. This means that our program should be able to create cats of two types - with a name and age for the first cat, and only with a name - for the second cat. To do this, we will overload the constructor: public class Cat ( String name; int age; //for the first cat //for the second cat public Cat (String name) ( this . name = name; ) public static void main (String args) ( Cat barsik = new Cat ("Barsik" , 5 ) ; Cat streetCatNamedBob = new Cat ("Bob" ) ; ) ) to the original constructor with the “name” and “age” parameters, we added another one, only with the name. In the same way, we overloaded methods in previous lessons. Now we can successfully create both variants of cats :)

Remember, at the beginning of the lecture, we said that you already used constructors, but you didn’t notice it yourself? And there is. The fact is that every class in Java has a so-called default constructor. It doesn't take any arguments, but it fires every time any object of any class is created. public class Cat ( public static void main (String args) ( Cat smears = new Cat () ; ) ) At first glance, this is invisible. Well, they created an object and created it, where is the work of the constructor? To see this, let's directly write an empty constructor for the Cat class, and inside it we will display some phrase in the console. If it is displayed, then the constructor has worked. public class Cat ( public Cat () ( System. out. println ("Created a cat!" ) ; ) public static void main (String args) ( Cat smears = new Cat () ; //this is where the default constructor worked } } Console output: Created a cat! Here is the confirmation! The default constructor is always invisibly present in your classes. But you need to know one more feature of it. The default constructor disappears from the class when you create some constructor with arguments. The proof of this, in fact, we have already seen above. Here in this code: public class Cat ( String name; int age; public Cat (String name, int age) ( this . name = name; this . age = age; ) public static void main (String args) ( Cat barsik = new Cat () ; //error! ) ) We couldn't create a cat without a name and age because we defined a constructor for Cat: string + number. The default constructor right after that disappeared from the class. Therefore, be sure to remember: if you need several constructors in your class, including the empty one, it needs to be created separately. For example, we are creating a program for a veterinary clinic. Our clinic wants to do good deeds and help homeless cats, about which we do not know either the name or age. Then our code should look like this: public class Cat ( String name; int age; //for domestic cats public Cat (String name, int age) ( this . name = name; this . age = age; ) //for street cats public Cat () ( ) public static void main (String args) ( Cat barsik = new Cat ("Barsik" , 5 ) ; Cat streetCat = new Cat () ; ) ) Now that we have explicitly written the default constructor, we can create cats of both types :) For a constructor (as for any method), the order of the arguments is very important. Let's swap the name and age arguments in our constructor. public class Cat ( String name; int age; public Cat (int age, String name) ( this . name = name; this . age = age; ) public static void main (String args) ( Cat barsik = new Cat ("Barsik " , 10 ) ; //error! ) ) Error! The constructor clearly describes: when creating a Cat object, it must be passed number and string, in that order. Therefore, our code does not work. Be sure to keep this in mind and keep this in mind when creating your own classes: public Cat (String name, int age) ( this . name = name; this . age = age; ) public Cat (int age, String name) ( this . age = age; this .name = name; ) These are two completely different constructors! If you express in one sentence the answer to the question Why do you need a constructor?, you can say: to ensure that objects are always in the correct state. When you use constructors, all your variables will be correctly initialized, and there will be no machines with speed 0 and other “wrong” objects in the program. Their use is very beneficial primarily for the programmer himself. If you initialize the fields yourself, there is a great risk of missing something and making a mistake. But this will not happen with the constructor: if you did not pass all the required arguments to it or mixed up their types, the compiler will immediately give an error. Separately, it is worth mentioning that inside the constructor you should not put the logic of your program. For this, you have at your disposal methods, in which you can describe all the functionality you need. Let's see why constructor logic is a bad idea: public class CarFactory ( String name; int age; int carsCount; public CarFactory (String name, int age, int carsCount) ( this . name = name; this . age = age; this.carsCount = carsCount;system.out.println( "She was founded" "On average she produces"+ (this . carsCount/ this . age) + "cars per year" ) ; ) public static void main (String args) ( CarFactory ford = new CarFactory ("Ford" , 115 , 50000000 ) ; ) ) We have a class CarFactory, describing a car factory. Inside the constructor, we initialize all the fields, and put the logic here: print some information about the factory to the console. It would seem that there is nothing wrong with this, the program worked perfectly. Console output: Our car factory is called Ford It was founded 115 years ago During that time, it produced 50,000,000 cars On average, it produces 434,782 cars per year But in fact, we have planted a time bomb. And such code can very easily lead to errors. Imagine that now we are talking not about Ford, but about the new factory "Amigo Motors", which has existed for less than a year and produced 1000 cars: public class CarFactory ( String name; int age; int carsCount; public CarFactory (String name, int age, int carsCount) ( this . name = name; this . age = age; this . carsCount = carsCount; System. out. println ( "Our car factory is called"+ this . name); System. out. println ( "She was founded"+ this . age + " years ago" ) ; System. out. println( "During this time it was produced"+ this . carsCount + "cars" ) ; System. out. println( "On average she produces"+ (this . carsCount/ this . age) + "cars per year" ) ; ) public static void main (String args) ( CarFactory ford = new CarFactory ("Amigo Motors" , 0 , 1000 ) ; ) ) Console output: Our car factory is called Amigo Motors Exception in thread "main" java.lang.ArithmeticException: / by zero It was founded 0 years ago During this time, it produced 1000 cars at CarFactory. (CarFactory.java:15) at CarFactory.main(CarFactory.java:23) Process finished with exit code 1 We've arrived! The program ended with some strange error. Can you guess what is the reason? The reason is in the logic we put in the constructor. Specifically, in this line: System. out. println( "On average she produces"+ (this . carsCount/ this . age) + "cars per year" ) ; Here we perform a calculation and divide the number of machines produced by the age of the factory. And since our factory is new (that is, it is 0 years old), the result is a division by 0, which is forbidden in mathematics. As a result, the program terminates with an error. How should we have done? Move all the logic into a separate method and call it, for example, printFactoryInfo() . You can pass it a CarFactory object as a parameter. You can also put all the logic there, and at the same time - the processing of possible errors, like ours with zero years. To each his own. Constructors are needed to correctly set the state of an object. For business logic, we have methods. Do not mix one with the other. Here are some useful links where you can read more about constructors:



Liked the article? Share it