OCA Java imtahan mövzuları

Understanding Equality

== operatoru ilə iki referansı müqayisə etdikdə hər iki referansın da eyni obyektə işarə edib etmədiyini müqayisə edir. equals() metodu ilə müqayisə etdikdə isə referansların dəyərlərini bir-biri ilə müqayisə edir. String classi equals() metodunu override edir deyə eyni dəyərə malik iki Stringi equals() ilə müqayisə etdikdə nəticə true verir. Ancaq StringBuilder classı equals() metodunu override etmir, ona görə də eyni dəyərə malik StringBuilder referanslarını equals() ilə müqayisə etdikdə nəticə false verir. Ümumiyyətlə əgər hər hansı bir class equals() metodunu override etmirsə, həmin classın referansı üzərindən equals() metodu çağırılsa, bu zaman Object classının equals() metodu çağırılır. Çünki bütün classlar aşkar şəkildə qeyd olunmasa da Object classından törəmədirlər və onun metodlarını varis alırlar. Bu mövzu Chapter 5’də ayrıca izah ediləcəkdir, hələlik isə bilməniz yetərlidir ki, Object classının equals() metodu dəyərləri müqayisə etmir, referansları müqayisə edir. Əgər referanslar eyni obyektə işarə edirsə, true qaytarır, digər hallarda isə false qaytarır.

public class Book {
    public static void main(String[] args) {
        Book b1 = new Book ();
        Book b2 = new Book ();
        Book b3 = b1;

        System.out.println(b1 == b3);       // true
        System.out.println(b1 == b2);       // false
        System.out.println(b1.equals(b2));  // false
    }
 }

Book classı göründüyü kimi equals() metodunu override etmir, belə olan halda bu class üçün == equals() eyni cür işləyir və eyni nəticəni verir.

İndi isə String StringBuilder ilə bağlı nümunələrə baxaq.

StringBuilder example:

StringBuilder one = new StringBuilder("java");
StringBuilder two = new StringBuilder("java");               
System.out.println(one == two);                  // false
System.out.println(one.equals(two));             // false

StringBuilder three = one.append(two);
System.out.println(one == three);                // true
System.out.println(one.equals(three));           // true
System.out.printf("%s,%s,%s%n",one,two,three);   // javajava, java, javajava

String example:

String x = "Hello World";
String y = "Hello World";
System.out.println(x == y);           // true
System.out.println(x.equals(y));      // true

String z = " Hello World".trim();
System.out.println(x == z);           // false
System.out.println(x.equals(z));      // true

String immutable`dır və String literal dəyərləri String Pool’da saxlanılır. JVM yaddaşda eyni literaldan ancaq bir ədəd yaradır. Yuxarıdakı nümunədə "Hello World" bir dəfə yaradılır pool`da saxlanılır. x y referanslarının hər ikisi də həmin o obyektə işarə edir.

" Hello World".trim(); literal dəyər olmadığından pool`da saxlanılmır, ona görə də x z eyni obyektə işarə etmirlər, amma eyni dəyərə malikdirlər. Burada da incə bir məqam var, aşağıdakı kod nümunəsinə baxaq:

String x = "Hello World";
String y = "Hello World".trim();
String z = "Hello World".toString();
System.out.println(x==y);     // true   
System.out.println(x==z);     // true

Bu mövzu ətraflı şəkildə coderanch forumunda müzakirə edilib:

http://www.coderanch.com/t/652234/ocajp/certification/Understanding-Equality-page-Java-OCA

 

String metodlar üzərindən bəzi nümunələrə baxaq:

String s1 = "test";
String s2 = s1.substring(0);
String s3 = s1.replace("e","e");
String s3_ = s1.replace('e','e');
String s4 = "test".trim();
String s5 = "test ".trim();
String s6 = s1.toString();

System.out.printf("substring: %s==%s returns %b%n", s1, s2, s1==s2);
System.out.printf("replace1:  %s==%s returns %b%n", s1, s3, s1==s3);
System.out.printf("replace2:  %s==%s returns %b%n", s1, s3_, s1==s3_);
System.out.printf("trim1:     %s==%s returns %b%n", s1, s4, s1==s4);
System.out.printf("trim2:     %s==%s returns %b%n", s1, s5, s1==s5);
System.out.printf("toString:  %s==%s returns %b%n", s1, s6, s1==s6);

Output:

  • substring:  test==test returns true
    replace1:   test==test returns false
    replace2:   test==test returns true
    trim1:      test==test returns true
    trim2:      test==test returns false
    toString:   test==test returns true

P.S. replace() char ilə olanda true qaytarır.

 

Primitiv wrapper classların (Integer, Double, Float və s.) equals() metodu ilə istifadəsi zamanı aşağıdakı 3 qayda keçərlidir:

  1. symmetric  ⇒  a.equals(b) ilə b.equals(a) eyni nəticəni qaytarır;
  2. transitive   ⇒   əgər a.equals(b)b.equals(c) geriyə true qaytarırsa, o zaman a.equals(c)true qaytaracaq;
  3. reflexive     ⇒   a.equals(a) geriyə true qaytarır.

Aşağıdakı şəkildəki suala Enthuware test bankında rast gələcəksiniz. İmtahanda əvvəllər “drag-drop” tipli suallar olsa da hazırda bu formatda suallar imtahan testlərindən çıxarılıb. Amma bu sualın içərisində maraqlı məqamlar var, faydalı olacağından qeyd etməyi zəruri bildim.

enthuware-equality-in-java

  • i1 == i2 – geriyə false qaytarır, çünki referanslar fərqli obyektlərə işarə edir.
  • i1 == i3 – geriyə true qaytarır, çünki i3 primitiv tipdə olduğundan i1 “unboxed” edilərək primitiv tipə çevirilir və sonra müqayisə aparılır.
  • i1 == b1 – compile olunmur, çünki i1 b1 referansları eyni ierarxiyada olmayan classlara məxsusdur və compiler compile zamanı bunu tutur və başa düşür ki, bu referanslar eyni obyektə işarə edə bilməzlər.
  • i1.equals(i2) –  geriyə true qaytarır, çünki hər ikisi Integer obyektidir və dəyərləri də eynidir.
  • i1.equals(b1)i1.equals(g1) – geriyə false qaytarır, çünki müqayisə olunan dəyərlər fərqli classlara aiddir. == ilə müqayisədən fərqli olaraq equals() ilə müxtəlif classlara işarə edən referansların müqayisəsi zamanı compile xətası baş vermir, çünki equals() metodu parametr olaraq Object tipi qəbul edir. Bütün wrapper classların equals() metodunun gövdəsində ilk olaraq müqayisə edilən obyektlərin eyni classa aid olub olmadığı yoxlanılır. Əgər eyni classa aid deyilsə, o zaman dəyərlərin yoxlanılması aparılmır, birbaşa false qaytarılır. Integer metodunun equals() metoduna baxsaq bu proses aydın olacaq:
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
  return false;
}

 

Wrapper classlar ilə bağlı digər maraqlı bir nümunəyə Coderanch forumunda rast gələ bilərsiniz:

public static void main(String[] args) {
int myInt1 = 10;
Integer myInteger1 = 10;
Integer myInteger2 = 10;
Integer myInteger3 = new Integer(10);
Short myShort1 = 10;
Number myNumber1 = 10;
Double myDouble1 = 10.0;
Double myDouble2 = 10;    // DOES NOT COMPILE

System.out.println(myInt1 == myInteger1);   // true
System.out.println(myInt1 == myInteger3);   // true
System.out.println(myInt1 == myShort1);     // true
System.out.println(myInt1 == myNumber1);    // DOES NOT COMPILE
System.out.println(myInt1 == myDouble1);    // true

System.out.println(myInteger1 == myInteger2);   // true
System.out.println(myInteger1 == myInteger3);   // false
System.out.println(myInteger1 == myShort1);     // DOES NOT COMPILE
System.out.println(myInteger1 == myNumber1);    // true
System.out.println(myInteger1 == myDouble1);    // DOES NOT COMPILE

System.out.println(myShort1 == 10.0);           // true
System.out.println(myShort1 == myNumber1);      // false
System.out.println(myShort1 == myDouble1);      // DOES NOT COMPILE
}

 

Əlavə olaraq aşağıdakı nümunələrə baxmağınızda da fayda var:

String s1 = new String();
String s2 = new String();
System.out.println(s1.equals(s2));   // true, çünki equals metodunu implement edir

StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
System.out.println(sb1.equals(sb2));  // false, çünki equals metodunu implement etmir

ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
System.out.println(l1.equals(l2));   // true, çünki equals metodunu implement edir

List<StringBuilder> l3 = new ArrayList<>();
List<StringBuilder> l4 = new ArrayList<>();
l3.add(new StringBuilder("sb"));
l4.add(new StringBuilder("sb"));
System.out.println(l3.equals(l4));   // false

List<String> l5 = new ArrayList<>();
List<String> l6 = new ArrayList<>();
l5.add(new String("str"));
l6.add(new String("str"));
System.out.println(l5.equals(l6));   // true

Object o1 = new Object();
Object o2 = new Object();
System.out.println(o1.equals(o2));   // false, səbəbi yuxarıda qeyd edilib

String str1 = "one";
String str2 = "two";
System.out.println(str1.equals(str1 = str2));   // false
System.out.println(str1.equals(str2 = str1));   // true

String s1 = "s1";
String s = "s";
System.out.println(s1 == s + 1);      // false
System.out.println(s1 == "s" + 1);    // true
final String e1 = "e1";
final String e = "e";
System.out.println(e1 == e + 1);      // true

String s1 = "java";
StringBuilder s2 = new StringBuilder("java");
if(s1 == s2)                  // DOES NOT COMPILE
    System.out.println("1");
if(s1.equals(s2))             // false
    System.out.println("2");

String a = "";
String b = "2cfalse";
a += 2;
a += 'c';
a += false;
System.out.println(a == "2cfalse");         // false
System.out.println(a.equals("2cfalse"));    // true
System.out.println(b == "2cfalse");         // true

StringBuilder strb = new StringBuilder(5);
String str = "";
str.equals(strb);             // false
str.equals(strb.toString());  // true

 

[topics lang=az]

About the author

Mushfiq Mammadov

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.