Defining Your Own Class
Info
Semua file yang ada pada contoh pada catatan ini ada pada package Ch4/J4_3_Defining_Your_Own_Class
An Employee Class
Info
Semua file yang ada pada contoh pada catatan ini ada pada package Ch4/J4_3_Defining_Your_Own_Class/J_1_An_Employee_Class
Mari kita buat class dengan nama Employee
.
Code
package Ch4.J4_3_Defining_Your_Own_Class.J_1_An_Employee_Class;
import java.math.BigDecimal;
import java.time.LocalDate;
public class EmployeeTest {
public static void main(String[] args) {
Employee[] employees = new Employee[4];
employees[0] = new Employee("Employee 1",new BigDecimal("7800000"),LocalDate.of(2023,6,5));
employees[1] = new Employee("Employee 2",new BigDecimal("7800000"),LocalDate.of(2023,6,5));
employees[2] = new Employee("Employee 3",new BigDecimal("7800000"),LocalDate.of(2023,6,5));
employees[3] = new Employee("Employee 4",new BigDecimal("7800000"),LocalDate.of(2023,6,5));
}
}
class Employee{
// instance
private String name;
private BigDecimal salary;
private LocalDate hireDay;
public Employee(String name, BigDecimal salary, LocalDate hireDay){
this.name = name;
this.salary = salary;
this.hireDay = hireDay;
}
public String getName() {
return name;
}
// Cutted, there is another method here
}
File diatas terdiri dari dua class, EmployeeTest
dan Employee
. Pada sebuah file, kita hanya boleh memiliki satu public class dan class yang di public harus memiliki nama yang sama dengan nama file.
Use of Multiple Source Files
Info
Semua file yang ada pada contoh pada catatan ini ada pada package Ch4/J4_3_Defining_Your_Own_Class/J_2_Use_Of_Multiple_Source_Files
Java programmer umumnya lebih memiliki membuat class kedalam source file masing-masing. Contoh, Employee Class ada pada Employe.java dan EmployeeTest class ada di EmployeeTest.java.
Code
package Ch4.J4_3_Defining_Your_Own_Class.J_2_Use_Of_Multiple_Source_Files;
import java.math.BigDecimal;
import java.time.LocalDate;
public class EmployeeTest {
public static void main(String[] args) {
Employee employee = new Employee("Farras",new BigDecimal("11000000"), LocalDate.of(2023,6,5));
System.out.printf("Nama\t: %s\nSalaray\t: %,.2f\nTanggal masuk\t: %s",
employee.getName(),
employee.getSalary(),
employee.getHireDay().toString());
}
}
package Ch4.J4_3_Defining_Your_Own_Class.J_2_Use_Of_Multiple_Source_Files;
import java.math.BigDecimal;
import java.time.LocalDate;
class Employee{
// instance
private String name;
private BigDecimal salary;
private LocalDate hireDay;
public Employee(String name, BigDecimal salary, LocalDate hireDay){
this.name = name;
this.salary = salary;
this.hireDay = hireDay;
}
public String getName() {
return name;
}
// Cutted, there is another method here
}
Declaring Local Variables with var
Semenjak Java 10, kita dapat mendeklarasi (wajib inisiasi juga) local variable menggunakan keyword var
sebagai spesifikasi type data variabel.
Warning
var
hanya bisa digunakan pada local variables didalam sebauh method.
Code
package Ch4.J4_3_Defining_Your_Own_Class;
import Ch4.J4_3_Defining_Your_Own_Class.J_2_Use_Of_Multiple_Source_Files.Employee;
import java.math.BigDecimal;
import java.time.LocalDate;
public class J_3_Declaring_Variable_Using_var {
public static void main(String[] args) {
Employee employeeOld = new Employee("Muhammad Farras",new BigDecimal(12000000),
LocalDate.of(2023,5,6));
var employee = new Employee("Muhammad Farras",new BigDecimal(12000000),
LocalDate.of(2023,5,6));
}
}
Working with null
References
Info
Semua file yang ada pada contoh pada catatan ini ada pada package Ch4/J4_3_Defining_Your_Own_Class/J_4_Working_With_null_Reference
Object variable menampung sebuah referensi ke sebuah objek atau special value null
yang mengidikasi bahwa variable tersebut belum merujuk ke objek apapun itu.
Kita harus berhati-hati dengan nilai null
. Karena jika kita memanggil method dari sebauh variable object yang bernilai null
akan menyebabkan !#java NullPointerException
.
try {
Employee employee1 = null;
System.out.println(employee1.getName());
// Without catch this exception, the app will terminate
}
catch (NullPointerException ex){
System.out.println(ex.getMessage());
}
index out of bounds
jika program kita tidak menangkap exception tersebut maka program akan berhenti terminate.
Ketika kita mendefinisikan sebauh class, sangat baik jika kita menetahui field mana yang bisa menerima nilai null
dan mana yang tidak. Pada contoh ini, kita tidak ingin properties name
, salary
dan hireDay
menerima nilai null
.
Ada dua solusi untuk mengubah null
kedalam non-null value.
Pertama
- Menggunakan cara primitive
Kedua
- Menggunakan statick fungsi dari class
Object
.
Namun ada cara yang lebih baik adalah menolak nilai null
. Gunakan Objects.requireNonNull()
.
Jika seseorang membuat objek Employee dengan memberikan parameter hireDay
nilai null
, maka NullPointerException
akan terjadi. pertama memang terlihat tidak berguna, namun ternyata ada dua manfaat.:
- Laporan exception akan terpampang deskripsi masalahnya
- Expcetion akan melaporkan lokasi persis masalah terjadi padakode. Karena,
NullPointerException
bisa terjadi dimana saja dan sulit untuk melacaknya, denga menggunakan methodObjects.requireNonNull()
kita dapat dengan mudah (alhamdulillah) melacak error akibatNullPonterException
yang terjadi.
All Code
package Ch4.J4_3_Defining_Your_Own_Class.J_4_Working_With_null_Reference;
import java.math.BigDecimal;
import java.time.LocalDate;
public class EmployeeTest {
public static void main(String[] args) {
try {
Employee employee1 = null;
System.out.println(employee1.getName());
// Without catch this exception, the app will terminate
}
catch (NullPointerException ex){
System.out.println(ex.getMessage());
}
var employee2 = new Employee(null,new BigDecimal(2500000), LocalDate.now());
System.out.println(employee2);
var employee3 = new Employee(null,null, LocalDate.now());
System.out.println(employee3);
var employee4 = new Employee(null,null, null);
System.out.println(employee4);
}
}
Cannot invoke "Ch4.J4_2_Predefined_Class.J_8_Working_With_null_Reference.Employee.getName()" because "employee1" is null
Name : Unknown Name
Salary : 2,500,000.00
Hire Day : 2023-08-18
Name : Unknown Name
Salary : 0.00
Hire Day : 2023-08-18
Exception in thread "main" java.lang.NullPointerException: Hire day is require
at java.base/java.util.Objects.requireNonNull(Objects.java:259)
at Ch4.J4_2_Predefined_Class.J_8_Working_With_null_Reference.Employee.<init>(Employee.java:19)
at Ch4.J4_2_Predefined_Class.J_8_Working_With_null_Reference.EmployeeTest.main(EmployeeTest.java:24)
package Ch4.J4_3_Defining_Your_Own_Class.J_4_Working_With_null_Reference;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Objects;
public class Employee {
// instance
private String name;
private BigDecimal salary;
private LocalDate hireDay;
public Employee(String name, BigDecimal salary, LocalDate hireDay){
this.name = Objects.requireNonNullElse(name,"Unknown Name");
this.salary = (salary ==null)? new BigDecimal(0) : salary;
this.hireDay = Objects.requireNonNull(hireDay,"Hire day is require");
}
@Override
public String toString() {
return "Name\t\t: %s\nSalary\t\t: %,.2f\nHire Day\t: %s".
formatted(this.name,this.salary,this.hireDay.toString());
}
public String getName() {
return this.name;
}
}
Private Method
Info
Semua file yang ada pada contoh pada catatan ini ada pada package Ch4/J4_3_Defining_Your_Own_Class/J_5_Private_Method
Ketika mengimplementasi sebuah class, kita membuat semua instance fileds (Properties) menjadi private
karena `#!java public`` data sangat rawan (berbahaya, dapat dirubah secara langsung). Namun bagaimana dengan private method? kebanyakan method diset sebagai public, private method biasanya digunakan untuk beberapa keadaan saja. Misalnya, terkadang kita ingin memecah kode untuk perhitungan kedalam beberapa method. Dimana method yang dipecah tersebut sebagai pembantu komputasi dari method utama yang diset sebagai public. Dengan demikian methode helper tersebut tidak hanya digunakan pada method utama dan tidak dapat dipanggil mada method instance utamanya.
All Code
package Ch4.J4_3_Defining_Your_Own_Class.J_5_Private_Method;
import java.math.BigDecimal;
import java.time.LocalDate;
public class EmployeeTest {
public static void main(String[] args) {
var employee1 = new Employee(null,new BigDecimal(13000000), LocalDate.now());
System.out.println(employee1.nicePrint()); // java: nicePrint() has private access
}
}
package Ch4.J4_3_Defining_Your_Own_Class.J_5_Private_Method;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Objects;
public class Employee {
// instance
private String name;
private BigDecimal salary;
private LocalDate hireDay;
public Employee(String name, BigDecimal salary, LocalDate hireDay){
this.name = Objects.requireNonNullElse(name,"Unknown Name");
this.salary = (salary ==null)? new BigDecimal(0) : salary;
this.hireDay = Objects.requireNonNull(hireDay,"Hire day is require");
}
private String nicePrint(){
return "Name\t\t: %s\nSalary\t\t: %,.2f\nHire Day\t: %s".
formatted(this.name,this.salary,this.hireDay.toString());
}
@Override
public String toString() {
return this.nicePrint();
}
}
Final Instance Fields
Kita dapat mendifinisikan instance field sebagai final
. Denga demikian, field tersebut akan tetap memiliki nilai yang sama dari awal objek tersebut dibuat hinggai dihancurkan. Nilai pada field yang ditetapkan menjadi final
tidak akan pernah beruha nilainya dan tidak dapat di assign dengan nilai apapun.
Modifier final
berguna untuk fields dengan tipe primitive atau final immutable class. (Class immutable adalah class yang tidak dapat berubah nilainya, seperti String
).
Namun untuk mutable class, penggunaan final sedikit membingungkan, contoh dibawah ini kita menggunakan saah satu mutable class, StringBuilder
.
Code
package Ch4.J4_3_Defining_Your_Own_Class;
import java.time.LocalTime;
public class J_6_Final_Instance_Field {
public static void main(String[] args) {
var thisLog = new Logger();
thisLog.setNewDataLog("%s Update hase confirm".formatted(LocalTime.now()));
thisLog.setNewDataLog("%s Another confirmation is accepted".formatted(LocalTime.now()));
System.out.println(thisLog.getLog());
}
}
class Logger{
private final StringBuilder log;
public Logger(){
this.log = new StringBuilder();
}
public void setNewDataLog(String information){
this.log.append(information).append("\n");
}
public String getLog(){
return this.log.toString();
}
}
Kode diatas kita membuat properties log
menjadi final
, namun mengapa kita masih menggunakan append()
pada fields tersebut yang notabenya menambah isi dari fields tersebut. Jawabannya adalah, Keyword final
fungsinya adalah agar reference objek yang telah tersimpan pada variable object (log
) tidak akan pernah merujuk ke objek StringBuilder lainnya. Namun objek tersebut tetap dapat berubah, mutate