Phân biệt instanceof, Class.isInstance với Class.isAssignableFrom

Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu về sự khác nhau giữa Class.isInstance và Class.isAssignableFrom.

Setup

Trước tiên, để phân biệt cách sử dụng 2 method trên chúng ta cần chuẩn bị một Shape interface

public interface Shape {
}

Sau đó chúng ta sẽ tiến hành tạo 2 class implement Shape interface là Triangle.

public class Triangle implements Shape {
}

IsoscelesTriangle 

public class IsoscelesTriangle extends Triangle {
}

Class.isInstance

Method isInstance trên class có tính năng tương tự như toán tử instanceof. Method isInstance được giới thiệu trong Java 1.1 trả về true nếu tham số truyền vào không NULL và có thể chuyển đổi sang object của class đang sử dụng isInstance.

@Test
public void whenUsingIsInstanceProperly_desiredResultsHappen() {
    Shape shape = new Triangle();
    Triangle triangle = new Triangle();
    IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle();
    Triangle isoscelesTriangle2 = new IsoscelesTriangle();
    Shape nonspecificShape = null;
        
    assertTrue(Shape.class.isInstance(shape));
    assertTrue(Shape.class.isInstance(triangle));
    assertTrue(Shape.class.isInstance(isoscelesTriangle));
    assertTrue(Shape.class.isInstance(isoscelesTriangle2));
    assertFalse(Shape.class.isInstance(nonspecificShape));
        
    assertTrue(Triangle.class.isInstance(shape));
    assertTrue(Triangle.class.isInstance(triangle));
    assertTrue(Triangle.class.isInstance(isoscelesTriangle));
    assertTrue(Triangle.class.isInstance(isoscelesTriangle2));
        
    assertFalse(IsoscelesTriangle.class.isInstance(shape));
    assertFalse(IsoscelesTriangle.class.isInstance(triangle));
    assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle));
    assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle2));
}

Class.isAssignableFrom

Method Class.isAssignableFrom sẽ trả về true nếu Class phía bên trái mệnh đề là cùng hoặc là một superclass, superinterface của class được cung cấp phía bên phải mệnh đề (tham số đầu vào).

 

Test
public void whenUsingIsAssignableFromProperly_desiredResultsHappen() {
    Shape shape = new Triangle();
    Triangle triangle = new Triangle();
    IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle();
    Triangle isoscelesTriangle2 = new IsoscelesTriangle();
        
    assertFalse(shape.getClass().isAssignableFrom(Shape.class));
    assertTrue(shape.getClass().isAssignableFrom(shape.getClass()));
    assertTrue(shape.getClass().isAssignableFrom(triangle.getClass()));
    assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle.getClass()));
    assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle2.getClass()));
        
    assertFalse(triangle.getClass().isAssignableFrom(Shape.class));
    assertTrue(triangle.getClass().isAssignableFrom(shape.getClass()));
    assertTrue(triangle.getClass().isAssignableFrom(triangle.getClass()));
    assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle.getClass()));
    assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass()));
        
    assertFalse(isoscelesTriangle.getClass().isAssignableFrom(Shape.class));
    assertFalse(isoscelesTriangle.getClass().isAssignableFrom(shape.getClass()));
    assertFalse(isoscelesTriangle.getClass().isAssignableFrom(triangle.getClass()));
    assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle.getClass()));
    assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass()));
        
    assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(Shape.class));
    assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(shape.getClass()));
    assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(triangle.getClass()));
    assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle.getClass()));
    assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle2.getClass()));
}

Sự khác nhau giữa Class.isInstance và Class.isAssignableFrom

Có một số điểm khác biệt giữa 2 method này mà chúng ta có thể xem xét:

  • Để sử dụng isInstance, chúng ta cần chỉ định rõ một class tại thời điểm compile time.
  • isAssignableFrom có thể sử dụng với kiểu dữ liệu nguyên thủy.
  • Phương thức isAssignableFrom sẽ ném một NullPointerException nếu object được sử dụng ở một trong hai bên của biểu thức là null. Nếu bạn cung cấp giá trị null cho phương thức isInstance, nó sẽ trả về false.
  • Chúng ta nên nghĩ về isInstance như việc trả lời câu hỏi liệu object được cung cấp có phải là kiểu mà chúng ta đang so sánh với nó (trực tiếp hoặc thông qua interface hoặc thừa kế) hay không. Chúng ta có thể coi isAssignableFrom là câu trả lời cho câu hỏi liệu chúng ta có thể định nghĩa class trong tham số là object class hay không. Nói cách khác thì Triangle triangle = new IsoscelesTriange() có thể không?
 

Nguồn

https://www.baeldung.com/java-isinstance-isassignablefrom

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x