GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Java Core Marker Interface trong Java

Marker Interface trong Java

Đăng vào 30/03/2020 . Được đăng bởi GP Coder . 11333 Lượt xem . Toàn màn hình

Trong bài viết Abstract class và Interface trong Java, mình có giới thiệu về Marker Interface. Tuy nhiên, có một số bạn vẫn chưa hiểu rõ hoặc chưa biết trường hợp nào cần sử dụng nó. Trong bài này, chúng ta sẽ cùng tìm hiểu chi tiết hơn về Marker Interface trong Java và một số trường hợp sử dụng Marker Interface.

Nội dung

  • 1 Marker (hay Tagging) Interface trong Java là gì?
  • 2 Built-in marker interface trong Java
  • 3 Chúng ta có thể sử dụng Marker Interface ở đâu?
  • 4 Custom Marker Interface
  • 5 Marker Interface vs. Annotation

Marker (hay Tagging) Interface trong Java là gì?

Marker Interface là một interface không có bất kỳ phương thức và thuộc tích nào bên trong nó. Nó cung cấp thông tin run-time type về object, vì vậy compiler và JVM có thêm thông tin về đối tượng thể thực hiện một số hoạt động hữu ích.

Một marker interface còn được gọi là một tagging interface.

Ví dụ:


public interface Serializable {
}

Built-in marker interface trong Java

Một số marker interface hiện có trong (built-in) Java: java.io.Serializable, java.lang.Cloneable, java.rmi.Remote, java.util.RandomAccess, java.util.EventListener, …

java.io.Serializable được sử dụng để đánh dấu đối tượng Serialize. Khi chúng ta gọi phương thức ObjectOutputStream.writeObject(), JVM sẽ kiểm tra đối tượng có implement một marker interface Serializable hay không. Nếu không, sẽ throw một exception NotSerializableException. Vì vậy đối tượng sẽ không được Serialize sang output stream object. Chi tiết các bạn xem bài viết “Serialization và Deserialization trong java“.

Tương tự, java.lang.Cloneable là một marker interface để nói với JVM rằng, đối tượng có thể call Object.clone() method. Nếu chúng ta thực hiện clone một object mà không được implement một marker interface Clonable, thì sẽ gặp một exception CloneNotSupportedException. Chi tiết về Clone và Clonable, các bạn xem lại bài viết “Object Cloning trong Java“.

Chúng ta có thể sử dụng Marker Interface ở đâu?

Có hai mục đích thiết kế chủ yếu của marker interface là:

  • Tạo một cha chung: Như với EventListener interface, mà được kế thừa bởi hàng tá các interface khác trong Java API, bạn có thể sử dụng một tagging interface để tạo một cha chung cho một nhóm interface. Ví dụ, khi một interface kế thừa EventListener, thì JVM biết rằng interface cụ thể này đang được sử dụng trong một event.
  • Thêm một kiểu dữ liệu tới một class: Đó là khái niệm tagging. Một class mà triển khai một tagging interface không cần định nghĩa bất kỳ phương thức nào, nhưng class trở thành một kiểu interface thông qua tính đa hình (polymorphism).
  • Thực hiện một số pre-processing trên các class, đặc biệt hữu dụng để phát triển các API và Framework giống như Sping, Struts.
  • Giúp cho code coverage và build tools để find bug dựa trên một behavior cụ thể của marker interface.

Custom Marker Interface

Trong ví dụ bên dưới, chúng ta tạo một Marker Interface gọi là SafeDeletable. Interface này chỉ ra rằng một đối tượng không được xoá khỏi database, chỉ được set flag là delete.

Marker interface:


interface SafeDeletable { }

Chúng ta có 2 đối tượng:

  • Order: đối tượng này có thể xoá khỏi database.
  • Customer: đối tượng này không thể xoá khỏi database, cần set flad delete khi được yêu cầu xoá.

class Order {}

class Customer implements SafeDeletable {}

Chương trình chúng ta như sau:


public class InterfaceMarkerExample {

    public static void delete(Object obj) {
        if (obj instanceof SafeDeletable) {
            System.out.println("Set flag to delete: " + obj.getClass());
        } else {
            System.out.println("Call delete object from database: " + obj.getClass());
        }
    }

    public static void main(String[] args) {

         delete(new Order());
         delete(new Customer());
    }
}

Output:


Call delete object from database: class com.gpcoder.Order
Set flag to delete: class com.gpcoder.Customer

Marker Interface vs. Annotation

Tương tự như Marker Interface, chúng ta có thể sử dụng Annotation cho cùng mục đích. Chúng ta có thể chỉ giới hạn sử dụng Annotation ở mức class giống như interface bằng cách khai báo java.lang.annotation.ElementType là TYPE.

Hãy xem cách sử dụng Annotation để thay thế cho Marker Interface ở trên:


@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface SafeDeletable {

}

class Order { }

@SafeDeletable
class Customer{ }

public class AnnotationMarkerExample {

    public static void delete(Object obj) {
        if (obj.getClass().isAnnotationPresent(SafeDeletable.class)) {
            System.out.println("Set flag to delete: " + obj.getClass());
        } else {
            System.out.println("Call delete object from database: " + obj.getClass());
        }
    }

    public static void main(String[] args) {

         delete(new Order());
         delete(new Customer());
    }
}

Một câu hỏi đặt ra là có phải Annotation có thể thay thế 100% Marker interface?

Chúng ta có thể sử dụng Annotation để thay thế cho Marker interface, tuy nhiên trong một số trường hợp sẽ khó khăn nếu sử dụng Annotation. Chẳng hạn trong ví dụ trên, nếu chúng ta có một class con của Customer :


class VipCustomer extends Customer {}

Nếu sử dụng Marker inetrface, mặc định class VipCustomer cũng được đánh dấu là SafeDeletable vì tính kế thừa của Java. Tuy nhiên, với Annotation, chúng ta cần đánh dấu lại Annotation SafeDeletable cho class VipCustomer. Kế thừa cũng là một bất lợi của Marker Interface so với Annotation là chúng ta không thể bỏ Marker Interface ở subclass, với Annotation thì không cần làm gì thêm.

Vì interface cho chúng ta tính đa hình (polymorphism), nên chúng ta có thể sử dụng để type check tại thời điểm compile time. Chẳng hạn, chúng ta có class DocumentTransferExecutor, class này chỉ chấp nhận transfer cho những document có implement marker interface DocumentTransferable. Thay vì nhận vào một Object type, chúng ta có thể chỉ định là một Marker interface để tránh developer truyền sai parameter type (đối tượng không phải là document) hay cast object trong quá trình xử lý.


interface DocumentTransferable { }

class DocumentTransferExecutor {

    public void transfer(DocumentTransferable obj) { }
}

Tóm lại, marker interface trong Java được sử dụng để chỉ ra một cái gì đó cho complier, JVM hoặc bất kỳ công cụ nào khác. Hiện nay, hầu hết các developer ủng hộ các Annotation để giải quyết một số vấn đề tương tự thay vì dùng marker interface. Mặc dù các marker interface vẫn đang được sử dụng, nhưng chúng nên được sử dụng cẩn thận vì tính kế thừa của nó.

4.9
35
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Basic Java, Java Core, Reflection Được gắn thẻ: Annotation, Basic Java

Hibernate Lifecycle
Hibernate Cache

Có thể bạn muốn xem:

  • Semaphore trong Java (18/09/2019)
  • Phân biệt JVM, JRE, JDK (18/10/2017)
  • Một số ký tự đặc biệt trong Java (20/10/2017)
  • Mệnh đề Switch-case trong java (26/10/2017)
  • Kiểu dữ liệu Ngày Giờ (Date Time) trong java (29/10/2017)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (98056 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (97696 lượt xem)
  • Giới thiệu Design Patterns (87759 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (86427 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83830 lượt xem)

Nội dung bài viết

  • 1 Marker (hay Tagging) Interface trong Java là gì?
  • 2 Built-in marker interface trong Java
  • 3 Chúng ta có thể sử dụng Marker Interface ở đâu?
  • 4 Custom Marker Interface
  • 5 Marker Interface vs. Annotation

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link