2-2.Jetpack 之 Room 简单编码模板(优化版)(Entity、DAO、Database、Repository)

devtools/2024/10/4 14:53:20/

一、Room

1、Room 概述
  • Room 是 Jetpack 中的一个重要成员,它是一个持久化库,它为管理数据库提供了简单强大的方法
2、Room 引入
  • 在模块级 build.gradle 中引入相关依赖
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"

二、Room 简单案例

1、Application
  • MyApplication.java
package com.my.room.application;import android.app.Application;
import android.content.Context;public class MyApplication extends Application {public static final String TAG = MyApplication.class.getSimpleName();private static Context context;@Overridepublic void onCreate() {super.onCreate();context = this;}public static Context getContext() {return context;}
}
2、Entity
  • Staff.java
package com.my.room.entity;import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;@Entity(tableName = "Staff")
public class Staff {@PrimaryKey(autoGenerate = true)public Long id;@ColumnInfo(name = "name")public String name;@ColumnInfo(name = "age")public Integer age;@ColumnInfo(name = "cardNum")public String cardNum;@Overridepublic String toString() {return "Staff{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", cardNum='" + cardNum + '\'' +'}';}
}
3、DAO
  • StaffDAO.java
package com.my.room.dao;import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;import com.my.room.entity.Staff;import java.util.List;@Dao
public interface StaffDAO {@Insertvoid insert(Staff staff);@Deletevoid delete(Staff staff);@Updatevoid update(Staff staff);@Query("SELECT * FROM Staff")List<Staff> queryAll();
}
4、Database
  • MyDatabase.java
package com.my.room.database;import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;import com.my.room.application.MyApplication;
import com.my.room.dao.StaffDAO;
import com.my.room.entity.Staff;@Database(entities = {Staff.class}, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {public static final String TAG = MyDatabase.class.getSimpleName();public static final String DATABASE_NAME = "test.db";private static MyDatabase myDatabase;public static MyDatabase getInstance() {if (myDatabase == null) {myDatabase = Room.databaseBuilder(MyApplication.getContext(), MyDatabase.class, DATABASE_NAME).build();}return myDatabase;}public abstract StaffDAO getStaffDAO();
}
5、Repository Observer
  1. InsertObserver.java
package com.my.room.repository.observer;public interface InsertObserver {void onSuccess();void onError(String msg);
}
  1. DeleteObserver.java
package com.my.room.repository.observer;public interface DeleteObserver {void onSuccess();void onError(String msg);
}
  1. UpdateObserver.java
package com.my.room.repository.observer;public interface UpdateObserver {void onSuccess();void onError(String msg);
}
  1. QueryAllObserver.java
package com.my.room.repository.observer;import java.util.List;public interface QueryAllObserver<T> {void onResult(List<T> ts);
}
6、Repository
  1. RepositoryItem.java
package com.my.room.repository;public class RepositoryItem<T> {public static final int CODE_SUCCESS = 1;public static final int CODE_ERROR = 2;private int code;private String msg;private T data;public RepositoryItem(int code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "RepositoryItem{" +"code=" + code +", msg='" + msg + '\'' +", data=" + data +'}';}
}
  1. StaffRepository.java
package com.my.room.repository;import android.os.AsyncTask;import com.my.room.dao.StaffDAO;
import com.my.room.database.MyDatabase;
import com.my.room.entity.Staff;
import com.my.room.repository.observer.DeleteObserver;
import com.my.room.repository.observer.InsertObserver;
import com.my.room.repository.observer.QueryAllObserver;
import com.my.room.repository.observer.UpdateObserver;import java.util.List;public class StaffRepository {private MyDatabase myDatabase;private StaffDAO staffDAO;public StaffRepository() {myDatabase = MyDatabase.getInstance();staffDAO = myDatabase.getStaffDAO();}// ====================================================================================================public void insert(Staff staff, InsertObserver insertObserver) {new InsertAsyncTask(staff, insertObserver).execute();}public void delete(Staff staff, DeleteObserver deleteObserver) {new DeleteAsyncTask(staff, deleteObserver).execute();}public void update(Staff staff, UpdateObserver updateObserver) {new UpdateAsyncTask(staff, updateObserver).execute();}public void queryAll(QueryAllObserver<Staff> queryAllObserver) {new QueryAllAsyncTask(queryAllObserver).execute();}// ====================================================================================================private class InsertAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private InsertObserver insertObserver;public InsertAsyncTask(Staff staff, InsertObserver insertObserver) {this.staff = staff;this.insertObserver = insertObserver;}@Overrideprotected RepositoryItem doInBackground(Void... voids) {try {staffDAO.insert(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {insertObserver.onSuccess();} else {insertObserver.onError(repositoryItem.getMsg());}}}private class DeleteAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private DeleteObserver deleteObserver;public DeleteAsyncTask(Staff staff, DeleteObserver deleteObserver) {this.staff = staff;this.deleteObserver = deleteObserver;}@Overrideprotected RepositoryItem<Object> doInBackground(Void... voids) {try {staffDAO.delete(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<Object> repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {deleteObserver.onSuccess();} else {deleteObserver.onError(repositoryItem.getMsg());}}}private class UpdateAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private UpdateObserver updateObserver;public UpdateAsyncTask(Staff staff, UpdateObserver updateObserver) {this.staff = staff;this.updateObserver = updateObserver;}@Overrideprotected RepositoryItem<Object> doInBackground(Void... voids) {try {staffDAO.update(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<Object> repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {updateObserver.onSuccess();} else {updateObserver.onError(repositoryItem.getMsg());}}}private class QueryAllAsyncTask extends AsyncTask<Void, Void, RepositoryItem<List<Staff>>> {private QueryAllObserver<Staff> queryAllObserver;public QueryAllAsyncTask(QueryAllObserver<Staff> queryAllObserver) {this.queryAllObserver = queryAllObserver;}@Overrideprotected RepositoryItem<List<Staff>> doInBackground(Void... voids) {try {List<Staff> staffs = staffDAO.queryAll();return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, staffs);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<List<Staff>> repositoryItem) {super.onPostExecute(repositoryItem);queryAllObserver.onResult(repositoryItem.getData());}}
}
7、Activity Layout
  • activity_staff.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".StaffActivity"><Buttonandroid:id="@+id/btn_insert"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/btn_delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/btn_insert" /><Buttonandroid:id="@+id/btn_update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/btn_delete" /><Buttonandroid:id="@+id/btn_query_all"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/btn_update" />
</androidx.constraintlayout.widget.ConstraintLayout>
8、Activity Code
  • StaffActivity.java
package com.my.room;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.widget.Button;import com.my.room.entity.Staff;
import com.my.room.repository.StaffRepository;
import com.my.room.repository.observer.DeleteObserver;
import com.my.room.repository.observer.InsertObserver;
import com.my.room.repository.observer.UpdateObserver;public class StaffActivity extends AppCompatActivity {public static final String TAG = StaffActivity.class.getSimpleName();private StaffRepository staffRepository;private Button btnInsert;private Button btnDelete;private Button btnUpdate;private Button btnQueryAll;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_staff);staffRepository = new StaffRepository();btnInsert = findViewById(R.id.btn_insert);btnDelete = findViewById(R.id.btn_delete);btnUpdate = findViewById(R.id.btn_update);btnQueryAll = findViewById(R.id.btn_query_all);btnInsert.setOnClickListener(v -> {Staff staff = new Staff();staff.name = "jack";staff.age = 20;staff.cardNum = "staff-001";staffRepository.insert(staff, new InsertObserver() {@Overridepublic void onSuccess() {Log.i(TAG, "------------------------------ insert success");}@Overridepublic void onError(String msg) {Log.i(TAG, "------------------------------ insert error - " + msg);}});});btnDelete.setOnClickListener(v -> {Staff staff = new Staff();staff.id = 1L;staffRepository.delete(staff, new DeleteObserver() {@Overridepublic void onSuccess() {Log.i(TAG, "------------------------------ delete success");}@Overridepublic void onError(String msg) {Log.i(TAG, "------------------------------ delete error - " + msg);}});});btnUpdate.setOnClickListener(v -> {Staff staff = new Staff();staff.id = 1L;staff.name = "jack";staff.age = 30;staff.cardNum = "staff-002";staffRepository.update(staff, new UpdateObserver() {@Overridepublic void onSuccess() {Log.i(TAG, "------------------------------ update success");}@Overridepublic void onError(String msg) {Log.i(TAG, "------------------------------ update error - " + msg);}});});btnQueryAll.setOnClickListener(v -> {staffRepository.queryAll(staffs -> {if (staffs == null) {Log.i(TAG, "------------------------------ queryAll - staffs is null");return;}if (staffs.size() == 0) {Log.i(TAG, "------------------------------ queryAll - staffs is empty");return;}for (Staff staff : staffs)Log.i(TAG, "------------------------------ queryAll - " + staff);});});}
}
Test
  • 增 -> 查 -> 改 -> 查 -> 删 -> 查,输出结果
I/StaffActivity: ------------------------------ insert success
I/StaffActivity: ------------------------------ queryAll - Staff{id=1, name='jack', age=20, cardNum='staff-001'}
I/StaffActivity: ------------------------------ update success
I/StaffActivity: ------------------------------ queryAll - Staff{id=1, name='jack', age=30, cardNum='staff-002'}
I/StaffActivity: ------------------------------ delete success
I/StaffActivity: ------------------------------ queryAll - staffs is empty

三、Room 简单案例解析

1、Entity 解析
@Entity(tableName = "Staff")
public class Staff {@PrimaryKey(autoGenerate = true)public Long id;@ColumnInfo(name = "name")public String name;@ColumnInfo(name = "age")public Integer age;@ColumnInfo(name = "cardNum")public String cardNum;@Overridepublic String toString() {return "Staff{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", cardNum='" + cardNum + '\'' +'}';}
}
  • @Entity(tableName = "Staff"):指定 Staff 类为 Room 数据库中 Staff 表对应的实体类
  1. @PrimaryKey(autoGenerate = true):指定 id 字段为主键,并且它的值是自动生成的

  2. @ColumnInfo(name = "name"):指定 name 字段映射到表中的 name 列,@ColumnInfo(name = "age")@ColumnInfo(name = "cardNum") 同理

  • Staff 表会在 APP 首次安装时由 Room 根据 Staff 类创建,SQL 语句如下
CREATE TABLE IF NOT EXISTS Staff (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,age INTEGER,cardNum TEXT
);
2、DAO 解析
@Dao
public interface StaffDAO {@Insertvoid insert(Staff staff);@Deletevoid delete(Staff staff);@Updatevoid update(Staff staff);@Query("SELECT * FROM Staff")List<Staff> queryAll();
}
  • @Dao:指定 StaffDAO 接口与 Room 数据库进行交互,以操作 Staff 类,该接口使用 Room 相关注解来定义操作方法
  1. @Insert:插入数据,这里传递一个 Staff 对象作为参数,Room 将这个对象插入到数据库

  2. @Delete:删除数据,这里传递一个 Staff 对象作为参数,Room 基于该对象的 id 字段来删除相应的行

  3. @Update:修改数据,这里传递一个 Staff 对象作为参数,Room 基于该对象的 id 字段来修改相应的行

  4. @Query("SELECT * FROM Staff"):查询数据,查询表中的所有行

3、Database 解析
@Database(entities = {Staff.class}, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {public static final String TAG = MyDatabase.class.getSimpleName();public static final String DATABASE_NAME = "test.db";private static MyDatabase myDatabase;public static MyDatabase getInstance() {if (myDatabase == null) {myDatabase = Room.databaseBuilder(MyApplication.getContext(), MyDatabase.class, DATABASE_NAME).build();}return myDatabase;}public abstract StaffDAO getStaffDAO();
}
(1)注解解析
  • @Database:指定 MyDatabase 抽象类为 Room 数据库
  1. entities = {Staff.class}:指定这个数据库包含 Staff 类

  2. version = 1:指定数据库的版本号,当实体或数据库结构发生变化时,需要增加这个版本号

  3. exportSchema = false:指定不导出数据库的 schema

(2)思路解析
  1. 单例模式确保整个应用程序中只有一个 MyDatabase 实例对象

  2. 通过 Room.databaseBuilder 方法构建数据库,该方法需要三个参数,分别为上下文、数据库类、数据库名称

  3. 定义获取 StaffDao 实例对象的抽象方法,Room 将自动生成这个方法的实现

4、Repository 解析
package com.my.room.repository;import android.os.AsyncTask;import com.my.room.dao.StaffDAO;
import com.my.room.database.MyDatabase;
import com.my.room.entity.Staff;
import com.my.room.repository.observer.DeleteObserver;
import com.my.room.repository.observer.InsertObserver;
import com.my.room.repository.observer.QueryAllObserver;
import com.my.room.repository.observer.UpdateObserver;import java.util.List;public class StaffRepository {private MyDatabase myDatabase;private StaffDAO staffDAO;public StaffRepository() {myDatabase = MyDatabase.getInstance();staffDAO = myDatabase.getStaffDAO();}// ====================================================================================================public void insert(Staff staff, InsertObserver insertObserver) {new InsertAsyncTask(staff, insertObserver).execute();}public void delete(Staff staff, DeleteObserver deleteObserver) {new DeleteAsyncTask(staff, deleteObserver).execute();}public void update(Staff staff, UpdateObserver updateObserver) {new UpdateAsyncTask(staff, updateObserver).execute();}public void queryAll(QueryAllObserver<Staff> queryAllObserver) {new QueryAllAsyncTask(queryAllObserver).execute();}// ====================================================================================================private class InsertAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private InsertObserver insertObserver;public InsertAsyncTask(Staff staff, InsertObserver insertObserver) {this.staff = staff;this.insertObserver = insertObserver;}@Overrideprotected RepositoryItem doInBackground(Void... voids) {try {staffDAO.insert(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {insertObserver.onSuccess();} else {insertObserver.onError(repositoryItem.getMsg());}}}private class DeleteAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private DeleteObserver deleteObserver;public DeleteAsyncTask(Staff staff, DeleteObserver deleteObserver) {this.staff = staff;this.deleteObserver = deleteObserver;}@Overrideprotected RepositoryItem<Object> doInBackground(Void... voids) {try {staffDAO.delete(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<Object> repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {deleteObserver.onSuccess();} else {deleteObserver.onError(repositoryItem.getMsg());}}}private class UpdateAsyncTask extends AsyncTask<Void, Void, RepositoryItem<Object>> {private Staff staff;private UpdateObserver updateObserver;public UpdateAsyncTask(Staff staff, UpdateObserver updateObserver) {this.staff = staff;this.updateObserver = updateObserver;}@Overrideprotected RepositoryItem<Object> doInBackground(Void... voids) {try {staffDAO.update(staff);return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, null);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<Object> repositoryItem) {super.onPostExecute(repositoryItem);if (repositoryItem.getCode() == RepositoryItem.CODE_SUCCESS) {updateObserver.onSuccess();} else {updateObserver.onError(repositoryItem.getMsg());}}}private class QueryAllAsyncTask extends AsyncTask<Void, Void, RepositoryItem<List<Staff>>> {private QueryAllObserver<Staff> queryAllObserver;public QueryAllAsyncTask(QueryAllObserver<Staff> queryAllObserver) {this.queryAllObserver = queryAllObserver;}@Overrideprotected RepositoryItem<List<Staff>> doInBackground(Void... voids) {try {List<Staff> staffs = staffDAO.queryAll();return new RepositoryItem(RepositoryItem.CODE_SUCCESS, null, staffs);} catch (Exception e) {e.printStackTrace();return new RepositoryItem(RepositoryItem.CODE_ERROR, e.getMessage(), null);}}@Overrideprotected void onPostExecute(RepositoryItem<List<Staff>> repositoryItem) {super.onPostExecute(repositoryItem);queryAllObserver.onResult(repositoryItem.getData());}}
}
  • StaffRepository 类是对 StaffDAO 的封装,封装的主要目的是异步任务处理
(1)异步任务处理
  • 对于每种 StaffDAO 实例对象的操作都定义了一个继承 AsyncTask 的内部类,它用于安排操作在后台线程中执行,然后使用观察者模式来通知调用者
  1. InsertAsyncTask:负责在后台线程中执行插入操作,完成后(无论成功还是失败)通过 InsertObserver 通知调用者

  2. DeleteAsyncTask:负责在后台线程中执行删除操作,完成后(无论成功还是失败)通过 DeleteObserver 通知调用者

  3. UpdateAsyncTask:负责在后台线程中执行插入操作,完成后(无论成功还是失败)通过 UpdateObserver 通知调用者

  4. QueryAllAsyncTask:负责在后台线程中执行查询操作,完成后(无论成功还是失败)通过 QueryAllObserver 通知调用者

(2)补充
  1. 线程调度:数据库操作不能在 UI 线程执行,操作在后台线程中(doInBackground 方法)执行完成后,然后回到 UI 线程中(onPostExecute 方法)执行后续操作

  2. 异常处理:在异步任务种,捕获可能抛出的异常,例如,执行插入操作时主键冲突会抛出异常


http://www.ppmy.cn/devtools/121308.html

相关文章

华为OD机试 - 区间交叠问题 - 贪心算法(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

vue基于Spring Boot框架的高校实验室预约管理系统

目录 毕设制作流程功能和技术介绍系统实现截图开发核心技术介绍&#xff1a;使用说明开发步骤编译运行代码执行流程核心代码部分展示可行性分析软件测试详细视频演示源码获取 毕设制作流程 &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&am…

行为设计模式 -观察者模式- JAVA

观察者模式 一.简介二. 案例2.1 抽象主题&#xff08;Subject&#xff09;2.2 具体主题&#xff08;Concrete Subject&#xff09;2.3 抽象观察者&#xff08;Observer&#xff09;2.4 具体观察者&#xff08;Concrete Observer&#xff09;2.5 测试 三. 结论3.1 优缺点3.2 使用…

linux 查看端口占用

文章目录 查看端口占用使用lsof使用netstat 查看端口占用 使用lsof 可以使用lsof -i:端口号 来查看端口占用情况 lsof -i:8010 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 35653 zhanghe 10u IPv4 0xcac2e413ddf9c5b9 0t0 …

Debezium日常分享系列之:将Debezium移至基金会

Debezium日常分享系列之&#xff1a;将Debezium移至基金会 介绍为什么要移至基金会&#xff1f;支持和与红帽价值观的一致性社区反馈 我们正在考虑将Debezium移至一个软件基金会&#xff0c;以扩大我们的社区&#xff0c;使我们的路线图和决策更加开放透明&#xff0c;并鼓励多…

JavaSE——面向对象8:Object类详解(==与equals的区别、hashCode、toString方法)

目录 一、与equals()的区别 (一)是一个比较运算符 (二)equals是Object类中的方法&#xff0c;只能判断引用类型 (三)equals方法重写练习 1.练习1 2.练习2 3.练习3 二、hashCode方法 三、toString方法 1.默认返回&#xff1a;全类名(包名类名)哈希值的十六进制 (1)不…

【无人机设计与技术】设计内部和外部 PID 回路,用于控制四轴飞行器的姿态和位移

摘要 本文设计了一个用于四轴飞行器控制的内部和外部PID回路。外部PID回路控制飞行器的位移&#xff0c;而内部PID回路则用于控制飞行器的姿态。这种控制结构能够有效调节飞行器的姿态和位移&#xff0c;实现平稳飞行并响应给定的轨迹。通过Simulink仿真模型对控制效果进行了验…

python三局两胜游戏

分为以下步骤实现这个功能 1、猜拳 2、机器产生数值 3、人去猜数字&#xff0c;定义剪刀石头布 4、控制机器产生&#xff0c;123程序运行的时候可能会出现一点玄学问题&#xff0c;就是&#xff0c;提示n1这一行不符合pep8然后报错&#xff0c;不用管&#xff0c;运行就可以&am…