国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home 類庫下載 java類庫 Android process communication mechanism AIDL

Android process communication mechanism AIDL

Oct 31, 2016 am 11:32 AM

What is AIDL

AIDL stands for Android Interface Definition Language, which is Android Interface Description Language. It sounds very profound, but its essence is an auxiliary tool for generating inter-process communication interfaces. It exists in the form of an .aidl file. All the developer needs to do is to define the interface for inter-process communication in the file. When compiling, the IDE will generate a .java file that can be used by the project based on our .aidl interface file. , which is somewhat similar to what we call "syntactic sugar".

The syntax of AIDL is the same as that of java, but there are some slight differences in the package import. In Java, if two classes are in the same package, there is no need to import the package, but in AIDL, a package import declaration is required.

?

Detailed explanation of AIDL

Conceive a scenario: We have a library management system, which is implemented through CS mode. Specific management functions are implemented by the server process, and the client only needs to call the corresponding interface.

Then first define the ADIL interface of this management system.

We create a new aidl package in /rc. There are three files in the package: Book.java, Book.aidl, and IBookManager.aidl.

package com.example.aidl book

public class Book implements Parcelable {
  int bookId;
  String bookName;

  public Book(int bookId, String bookName) {
     this.bookId = bookId;
     this.bookName = bookName;
  }

  ...
}

package com.example.aidl;

Parcelable Book;

package com.example.aidl;

import com.example.aidl.Book;

inteface IBookManager {
   List<Book> getBookList();
   void addBook(in Book book);
}

The following are descriptions of these three files:

Book.java is the entity class we defined, which implements the Parcelable interface, so Book Classes can be transferred between processes.

Book.aidl is the declaration of this entity class in AIDL.

IBookManager is the interface for communication between the server and the client. (Note that in addition to the basic types in the AIDL interface, the direction must be added before the parameters, in represents input parameters, out represents output parameters, and inout represents input and output parameters)

After the compiler is compiled, android studio will be used for our project A .java file is automatically generated. This file contains three classes. These three classes are IBookManager, Stub and Proxy. These three classes are all static types. We can completely separate them. The three classes are defined as follows:

IBookManager

public interface IBookManager extends android.os.IInterface {

    public void addBook(net.bingyan.library.Book book) throws android.os.RemoteException;

    public java.util.List<net.bingyan.library.Book> getBookList() throws android.os.RemoteException;
}

Stub

public static abstract class Stub extends android.os.Binder implements net.bingyan.library.IBookManager {
        private static final java.lang.String DESCRIPTOR = "net.bingyan.library.IBookManager";

        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an net.bingyan.library.IBookManager interface,
         * generating a proxy if needed.  http://www.manongjc.com/article/1501.html
         */
        public static net.bingyan.library.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof net.bingyan.library.IBookManager))) {
                return ((net.bingyan.library.IBookManager) iin);
            }
            return new net.bingyan.library.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    net.bingyan.library.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = net.bingyan.library.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getBookList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<net.bingyan.library.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
}

Proxy

private static class Proxy implements net.bingyan.library.IBookManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * Demonstrates some basic types that you can use as parameters
             * and return values in AIDL.   http://www.manongjc.com/article/1500.html
             */
            @Override
            public void addBook(net.bingyan.library.Book book) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public java.util.List<net.bingyan.library.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<net.bingyan.library.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(net.bingyan.library.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
       }

The description of the three generated classes is as follows:

IBookManager This class is the interface we defined. Android studio adds a parent class to it and lets it inherit from The android.os.interface interface has only one method IBinder asBinder(), so there are three implemented methods in IBookManager. It is the window for communication between the server process and the client process.

Stub is an abstract class. This class inherits from the android.os.Binder class and implements the IBookManager interface. In Stub, the asBinder() interface method has been implemented, and there are two AIDL interface methods we defined for subclasses that inherit it to implement. It is used on the server side, so the server needs to implement these two methods.

Proxy, as the name suggests, is a proxy class. It is a proxy for the server on the client. It also implements the IBookManager interface and implements all methods in IBookManager. It is used on the client side and is the proxy of the server on the client side.

Now we analyze these three classes one by one:

IBookManager There is nothing to say about this class. It simply inherits the asInterface interface, and its function is to convert IBookManager into IBinder.

Proxy This class has been mentioned above. It is an encapsulation class of the inter-process communication mechanism. Its internal implementation mechanism is Binder, which we can easily see through the construction method. Its constructor accepts an IBinder type parameter named remote, which obviously represents the server. Let’s take a look at the methods addBook() and getBookList() in this class:

@Override
public void addBook(net.bingyan.library.Book book) throws android.os.RemoteException {
      android.os.Parcel _data = android.os.Parcel.obtain();
      android.os.Parcel _reply = android.os.Parcel.obtain();
      try {
            _data.writeInterfaceToken(DESCRIPTOR)
            if ((book != null)) {
                _data.writeInt(1);
                book.writeToParcel(_data, 0);
            } else {
                _data.writeInt(0);
            }
            mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
            _reply.readException();
       } finally {
            _reply.recycle();
            _data.recycle();
       }
}
@Override /* http://www.manongjc.com/article/1547.html */
public java.util.List<net.bingyan.library.Book> getBookList() throws android.os.RemoteException {
       android.os.Parcel _data = android.os.Parcel.obtain();
       android.os.Parcel _reply = android.os.Parcel.obtain();
       java.util.List<net.bingyan.library.Book> _result;
       try {
             _data.writeInterfaceToken(DESCRIPTOR);
             mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
             _reply.readException();
             _result = _reply.createTypedArrayList(net.bingyan.library.Book.CREATOR);
       } finally {
            _reply.recycle();
            _data.recycle();
       }
       return _result;
}

They are automatically implemented by the compiler. These two methods have many similarities, which can be revealed here: these two methods are the client The process calls the window of the server process. At the beginning of these two methods, they both define two Parcel (Chinese translation: package) objects. The Parcel class looks familiar to us. Yes, the parameters of writeToParcel() in the Book class and createFromParcel() in the CREATOR are of the Parcel type. The documentation on this class is explained as follows:

Container for a message (data and object references) that can be sent through an IBinder. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC (using the various methods here for writing specific types, or the general {@link Parcelable} interface), and references to live {@link IBinder} objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel.

Translation: Proxy is a proxy that can pass IBinder A container for messaging. A Parcel can contain serializable data, which will be deserialized at the other end of the IPC; it can also contain a reference to an IBinder object, which will cause the other end to receive a proxy object of type IBinder. This proxy object Connected to the original IBinder object in Parcel.

The following is a visual explanation with a picture:

Android process communication mechanism AIDL

As shown in the picture, we can intuitively see that the server uses Parcel as the data package and relies on Binder to communicate with the client. The data package is the object after serialization.

As mentioned above, these two methods define two Parcel objects, called _data and _reply respectively. Figuratively speaking, from the perspective of the client, _data is the data package sent by the client to the server, and _reply is the server The data package sent to the client.

After that, we started to use these two objects to communicate with the server. We can observe that both methods have such a method call mRemote.transact(), which has four parameters. The first parameter is We will talk about the meaning later. The second parameter _data is responsible for sending data packages such as the parameters of interface methods to the server, and the third parameter _reply is responsible for receiving data packages such as the return values ??of interface methods from the server. This line of code only has a simple method call, but it is the core part of AIDL communication. It actually makes a remote method call (the client calls the server Stub method with the same name through the interface method exposed by the local proxy Proxy), so you can think of It is a time consuming operation.

In our example:

void addBook(Book book) needs to use _data to send the parameter Book:book to the server. The way to send it is to package Book into _data through the writeToParcel(Parcel out) method it implements, as As you can imagine, _data is actually the parameter out. Do you remember the implementation of this method in Book? We package the fields of Book into Parcel one by one.

List getBookList() needs to use _reply to receive the return value List:books from the server. The method is to pass the static field CREATOR in Book as a parameter into the createTypedArrayList() method of _reply. Remember that in Book The CREATOR? At that time, were you curious about how to use this static field? Now everything is clear, we need to rely on this object (we can call it "deserializer" for ease of understanding) to deserialize the data on the server side and regenerate a serializable object or object array. Obviously CREATOR generated List:books with the help of _reply.

Of course, _data and _reply in these two methods not only pass the object, but also pass some verification information. We don’t need to delve into this, but it should be noted that the order of Parcel packaging and unpacking must strictly correspond. For example, if the first packed value is int:i, then the first unpacked value should also be this integer value. That is, if the first call when packaging is Parcel.writeInt(int), the first call when unpacking should be Parcel.readInt().

At this point, the client’s Proxy has been explained. Let’s take a look at the server’s Stub.

Stub implements one of the methods of IBookManager. This is very simple. It simply returns itself, because Stub itself inherits from Binder, and Binder inherits from IBinder, so there is no problem. You may ask: Are there two methods that have not been implemented? These two methods are the interface methods we defined, and they are left to the server process to implement. In other words, we will need to define a Stub implementer in the server process. The following is an analysis of two important methods in Stub:

IBookManager asInterface(IBinder obj)

public static net.bingyan.library.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof net.bingyan.library.IBookManager))) {
                return ((net.bingyan.library.IBookManager) iin);
            }
            return new net.bingyan.library.IBookManager.Stub.Proxy(obj);
        }

這個方法的作用是將 Stub 類轉(zhuǎn)換成 IBookManager 這個接口,方法中有個判斷:如果我們的服務(wù)端進程和客戶端進程是同一進程,那么就直接將 Stub 類通過類型轉(zhuǎn)換轉(zhuǎn)成 IBookManager;如果不是同一進程,那么就通過代理類 Proxy 將 Stub 轉(zhuǎn)換成 IBookManager。為什么這么做,我們知道如果服務(wù)端進程和客戶端進程不是同一進程,那么它們的內(nèi)存就不能共享,就不能通過一般的方式進行通信,但是我們?nèi)绻约喝崿F(xiàn)進程間通信方式,對于普通開發(fā)者來說成本太大,因此編譯器幫我們生成了一個封裝了了進程間通信的工具,也就是這個 Proxy,這個類對底層的進程通信機制進行了封裝只同時暴露出接口方法,客戶端只需要調(diào)用這兩個方法實現(xiàn)進程間通信(其實就是方法的遠程調(diào)用)而不需要了解其中的細節(jié)。

有了這個方法,我們在客戶端可以借助其將一個 IBinder 類型的變量轉(zhuǎn)換成我們定義的接口 IBookManager,它的使用場景我們會在后面的實例中進行講解。

onTransact(int code, Parcel data, Parcel reply, int flags)

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
           switch (code) {
               case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
               }
               case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    net.bingyan.library.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = net.bingyan.library.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true; /*  http://www.manongjc.com/article/1499.html */
               }
               case TRANSACTION_getBookList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<net.bingyan.library.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
           }
           return super.onTransact(code, data, reply, flags);
}

這個方法我們是不是也很熟悉呢?我們在 Proxy 中也看到一個類似得方法 transact(int, Parcel, Parcel, int),它們的參數(shù)一樣,而且它們都是 Binder 中的方法,那么它們有什么聯(lián)系呢?

前面說了,transact() 執(zhí)行了一個遠程調(diào)用,如果說 transact() 是遠程調(diào)用的發(fā)起,那么 onTransact() 就是遠程調(diào)用的響應(yīng)。真實過程是客戶端發(fā)器遠程方法調(diào)用,android 系統(tǒng)通過底層代碼對這個調(diào)用進行響應(yīng)和處理,之后回調(diào)服務(wù)端的 onTransact() 方法,從數(shù)據(jù)包裹中取出方法參數(shù),交給服務(wù)端實現(xiàn)的同名方法調(diào)用,最后將返回值打包返回給客戶端。

需要注意的是 onTransact() 是在服務(wù)端進程的 Binder 線程池中進行的,這就意味著如果我們的要在 onTransact() 方法的中更新 UI,就必須借助 Handler。

這兩個方法的第一個參數(shù)的含義是 AIDL 接口方法的標識碼,在 Stub 中,定義了兩個常量作為這兩個方法的標示:

static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

如果 code == TRANSACTION_addBook,那么說明客戶端調(diào)用的是 addBook();如果 code == TRANSACTION_getBookList,那么客戶端調(diào)用的是 getBookList(),然后交由相應(yīng)的服務(wù)端方法處理。 用一張圖來表示整個通信過程:

Android process communication mechanism AIDL

了解了 AIDL 的整個過程,接下來就是 AIDL 在安卓程序中的應(yīng)用了。

AIDL 的使用

相信大家應(yīng)該都和清楚 Service 的使用了吧,Service 雖然稱作“服務(wù)”,并且運行于后臺,但是它們默認還是運行在默認進程的主線程中。其實讓 Service 運行在默認進程中,有點大材小用了。android 的很多系統(tǒng)服務(wù)都運行于單獨的進程中,供其他應(yīng)用調(diào)用,比如窗口管理服務(wù)。這樣做的好處是可以多個應(yīng)用共享同一個服務(wù),節(jié)約了資源,也便于集中管理各個客戶端,要注意問題的就是線程安全問題。

那么接下來我們就用 AIDL 實現(xiàn)一個簡單的 CS 架構(gòu)的圖書管理系統(tǒng)。

首先我們定義服務(wù)端:

BookManagerService

public class BookManagerService extends Service {

    private final List<Book> mLibrary = new ArrayList<>();

    private IBookManager mBookManager = new IBookManager.Stub() {
        @Override
        public void addBook(Book book) throws RemoteException {
            synchronized (mLibrary) {
                mLibrary.add(book);
                Log.d("BookManagerService", "now our library has " + mLibrary.size() + " books");
            }

        }

        @Override
        public List<Book> getBookList() throws RemoteException {
            return mLibrary;
        }
    };
 
    @Override  /*  http://www.manongjc.com/article/1496.html  */
    public IBinder onBind(Intent intent) {
        return mBookManager.asBinder();
    }

}

android:name=".BookManagerService"/>

服務(wù)端我們定義了 BookManagerService 這個類,在它里面我們創(chuàng)建了服務(wù)端的 Stub 對象,并且實現(xiàn)了需要實現(xiàn)的兩個 AIDL 接口方法來定義服務(wù)端的圖書管理策略。在 onBind() 方法中我們將 IBookManager 對象作為 IBinder 返回。我們知道,當(dāng)我們綁定一個服務(wù)時,系統(tǒng)會調(diào)用 onBinder() 方法得到服務(wù)端的 IBinder 對象,并將其轉(zhuǎn)換成客戶端的 IBinder 對象傳給客戶端,雖然服務(wù)端的 IBinder 和 客戶端的 IBinder 是兩個 IBinder 對象,但他們在底層都是同一個對象。我們在 xml 中注冊 Service 時給它指定了進程名,這樣 Service 就能運行在單獨的進程中了。

接下來看看客戶端的實現(xiàn):

Client

public class Client extends AppCompatActivity {

    private TextView textView;

    private IBookManager bookManager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.library_book_manager_system_client);

        Intent i  = new Intent(Client.this, BookManagerService.class);
        bindService(i, conn, BIND_AUTO_CREATE);

        Button addABook = (Button) findViewById(R.id.button);
        addABook.setOnClickListener(v -> {
            if (bookManager == null) return;
            try {
                bookManager.addBook(new Book(0, "book"));
                textView.setText(getString(R.string.book_management_system_book_count, String.valueOf(bookManager.getBookList().size())));
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        });

        textView = (TextView) findViewById(R.id.textView);
    }

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("Client -->", service.toString());

            bookManager = IBookManager.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("Client", name.toString());
        }
    };

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1"
    android:gravity="center">

    <Button
        android:text="http://www.manongjc.com/article/1495.html"
        android:layout_width="111dp"
        android:layout_height="wrap_content"
        android:id="@+id/button" />

    <TextView
        android:layout_marginTop="10dp"
        android:text="@string/book_management_system_book_count"
        android:layout_width="231dp"
        android:gravity="center"
        android:layout_height="wrap_content"
        android:id="@+id/textView" />
</LinearLayout>

我們的客戶端就是一個?Activity,onCreate()?中進行了服務(wù)的綁定,bindService()?方法中有一參數(shù)?ServiceConnection:conn,因為綁定服務(wù)是異步進行的,這個參數(shù)的作用就是綁定服務(wù)成功后回調(diào)的接口,它有兩個回調(diào)方法:一個是連接服務(wù)成功后回調(diào),另一個在與服務(wù)端斷開連接后回調(diào)。我們現(xiàn)在關(guān)心的主要是?onServiceConnected()?方法,在這里我們只做了一件事:將服務(wù)端轉(zhuǎn)換過來的?IBinder?對象轉(zhuǎn)換成 AIDL 接口,我們定義?IBookManager:bookManager?字段來保持對其的引用。這樣的話,我們就可以通過這個?bookManager?來進行方法的遠程調(diào)用。我們給客戶端的?Button?注冊事件:每一次點擊都會向服務(wù)端增加一本書,并且將圖書館現(xiàn)有的圖書數(shù)量顯示出來。

現(xiàn)在我們看看程序的運行效果:

Android process communication mechanism AIDL

每當(dāng)我們點擊按鈕,我們就成功的向服務(wù)端添加了一本書,說明我們通過 AIDL 跨進程通信成功了。

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to iterate over a Map in Java? How to iterate over a Map in Java? Jul 13, 2025 am 02:54 AM

There are three common methods to traverse Map in Java: 1. Use entrySet to obtain keys and values at the same time, which is suitable for most scenarios; 2. Use keySet or values to traverse keys or values respectively; 3. Use Java8's forEach to simplify the code structure. entrySet returns a Set set containing all key-value pairs, and each loop gets the Map.Entry object, suitable for frequent access to keys and values; if only keys or values are required, you can call keySet() or values() respectively, or you can get the value through map.get(key) when traversing the keys; Java 8 can use forEach((key,value)-&gt

Java Optional example Java Optional example Jul 12, 2025 am 02:55 AM

Optional can clearly express intentions and reduce code noise for null judgments. 1. Optional.ofNullable is a common way to deal with null objects. For example, when taking values ??from maps, orElse can be used to provide default values, so that the logic is clearer and concise; 2. Use chain calls maps to achieve nested values ??to safely avoid NPE, and automatically terminate if any link is null and return the default value; 3. Filter can be used for conditional filtering, and subsequent operations will continue to be performed only if the conditions are met, otherwise it will jump directly to orElse, which is suitable for lightweight business judgment; 4. It is not recommended to overuse Optional, such as basic types or simple logic, which will increase complexity, and some scenarios will directly return to nu.

Comparable vs Comparator in Java Comparable vs Comparator in Java Jul 13, 2025 am 02:31 AM

In Java, Comparable is used to define default sorting rules internally, and Comparator is used to define multiple sorting logic externally. 1.Comparable is an interface implemented by the class itself. It defines the natural order by rewriting the compareTo() method. It is suitable for classes with fixed and most commonly used sorting methods, such as String or Integer. 2. Comparator is an externally defined functional interface, implemented through the compare() method, suitable for situations where multiple sorting methods are required for the same class, the class source code cannot be modified, or the sorting logic is often changed. The difference between the two is that Comparable can only define a sorting logic and needs to modify the class itself, while Compar

How to fix java.io.NotSerializableException? How to fix java.io.NotSerializableException? Jul 12, 2025 am 03:07 AM

The core workaround for encountering java.io.NotSerializableException is to ensure that all classes that need to be serialized implement the Serializable interface and check the serialization support of nested objects. 1. Add implementsSerializable to the main class; 2. Ensure that the corresponding classes of custom fields in the class also implement Serializable; 3. Use transient to mark fields that do not need to be serialized; 4. Check the non-serialized types in collections or nested objects; 5. Check which class does not implement the interface; 6. Consider replacement design for classes that cannot be modified, such as saving key data or using serializable intermediate structures; 7. Consider modifying

How to handle character encoding issues in Java? How to handle character encoding issues in Java? Jul 13, 2025 am 02:46 AM

To deal with character encoding problems in Java, the key is to clearly specify the encoding used at each step. 1. Always specify encoding when reading and writing text, use InputStreamReader and OutputStreamWriter and pass in an explicit character set to avoid relying on system default encoding. 2. Make sure both ends are consistent when processing strings on the network boundary, set the correct Content-Type header and explicitly specify the encoding with the library. 3. Use String.getBytes() and newString(byte[]) with caution, and always manually specify StandardCharsets.UTF_8 to avoid data corruption caused by platform differences. In short, by

JavaScript Data Types: Primitive vs Reference JavaScript Data Types: Primitive vs Reference Jul 13, 2025 am 02:43 AM

JavaScript data types are divided into primitive types and reference types. Primitive types include string, number, boolean, null, undefined, and symbol. The values are immutable and copies are copied when assigning values, so they do not affect each other; reference types such as objects, arrays and functions store memory addresses, and variables pointing to the same object will affect each other. Typeof and instanceof can be used to determine types, but pay attention to the historical issues of typeofnull. Understanding these two types of differences can help write more stable and reliable code.

Java method references explained Java method references explained Jul 12, 2025 am 02:59 AM

Method reference is a way to simplify the writing of Lambda expressions in Java, making the code more concise. It is not a new syntax, but a shortcut to Lambda expressions introduced by Java 8, suitable for the context of functional interfaces. The core is to use existing methods directly as implementations of functional interfaces. For example, System.out::println is equivalent to s->System.out.println(s). There are four main forms of method reference: 1. Static method reference (ClassName::staticMethodName); 2. Instance method reference (binding to a specific object, instance::methodName); 3.

What is the 'static' keyword in Java? What is the 'static' keyword in Java? Jul 13, 2025 am 02:51 AM

InJava,thestatickeywordmeansamemberbelongstotheclassitself,nottoinstances.Staticvariablesaresharedacrossallinstancesandaccessedwithoutobjectcreation,usefulforglobaltrackingorconstants.Staticmethodsoperateattheclasslevel,cannotaccessnon-staticmembers,

See all articles