@Nonnull、@Nullable、空对象模式

本文详细解析了Spring框架中的@Nonnull、@Nullable注解,以及JDK中的@NotNull等注解的使用场景和差异。这些注解用于标记方法、参数、变量是否允许为null,有助于代码质量和错误预防。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring中: 

package org.springframework.lang;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;

@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierNickname
public @interface NonNull {
}
package org.springframework.lang;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;

@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull(
    when = When.MAYBE
)
@TypeQualifierNickname
public @interface Nullable {
}

@Nonnull、@Nullable( JSR305引入)可以用在方法、参数、变量上。@Nonnull表示不可以为Null,@Nullable表示可以为Null。想在加了@Nonnull后编码传入Null时有非空警告,必须有FindBugs插件配合,或者使用IDEA;运行时不检查。

JDK中:

package com.sun.istack.internal;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
public @interface NotNull {
}

 @NotNull( JSR303引入)可以用在方法、参数、变量、本地变量(var)中,运行时检查。

类似注解:

@Null 被注释的元素必须为null
@NotNull 被注释的元素不能为null,可以为空字符串
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min) 被注释的元素的大小必须在指定的范围内。
@Digits(integer,fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式。
@Email 被注释的元素必须是电子邮件地址
@Length 被注释的字符串的大小必须在指定的范围内
@Range 被注释的元素必须在合适的范围内
@NotEmpty:用在集合类上,不能为null,并且长度必须大于0
@NotBlank:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0

参考:jianshu.com/p/32327ca2365f

空对象模式用来替代Null,和@Nonnull一样可以避免NPE(Null Point Exception)。参考:https://www.runoob.com/design-pattern/null-object-pattern.html

你现在是一名资深的蓝牙工程师,请你详细讲解下面的BluetoothServiceBinder.java的代码: package com.android.server.bluetooth; 18 19 import static android.Manifest.permission.BLUETOOTH_CONNECT; 20 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; 21 import static android.Manifest.permission.DUMP; 22 import static android.Manifest.permission.LOCAL_MAC_ADDRESS; 23 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 24 25 import static com.android.server.bluetooth.BtPermissionUtils.checkConnectPermissionForDataDelivery; 26 import static com.android.server.bluetooth.BtPermissionUtils.getCallingAppId; 27 import static com.android.server.bluetooth.BtPermissionUtils.isCallerSystem; 28 29 import static java.util.Objects.requireNonNull; 30 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.RequiresPermission; 34 import android.app.AppOpsManager; 35 import android.bluetooth.BluetoothAdapter; 36 import android.bluetooth.IBluetooth; 37 import android.bluetooth.IBluetoothManager; 38 import android.bluetooth.IBluetoothManagerCallback; 39 import android.content.AttributionSource; 40 import android.content.Context; 41 import android.os.Build; 42 import android.os.IBinder; 43 import android.os.Looper; 44 import android.os.ParcelFileDescriptor; 45 import android.os.UserManager; 46 import android.permission.PermissionManager; 47 48 import androidx.annotation.RequiresApi; 49 50 import java.io.FileDescriptor; 51 import java.io.PrintWriter; 52 53 class BluetoothServiceBinder extends IBluetoothManager.Stub { 54 private static final String TAG = BluetoothServiceBinder.class.getSimpleName(); 55 56 private final BluetoothManagerService mBluetoothManagerService; 57 private final Context mContext; 58 private final UserManager mUserManager; 59 private final AppOpsManager mAppOpsManager; 60 private final PermissionManager mPermissionManager; 61 private final BtPermissionUtils mPermissionUtils; 62 private final Looper unusedmLooper; 63 64 BluetoothServiceBinder( 65 BluetoothManagerService bms, Looper looper, Context ctx, UserManager userManager) { 66 mBluetoothManagerService = bms; 67 unusedmLooper = looper; 68 mContext = ctx; 69 mUserManager = userManager; 70 mAppOpsManager = 71 requireNonNull( 72 ctx.getSystemService(AppOpsManager.class), 73 "AppOpsManager system service cannot be null"); 74 mPermissionManager = 75 requireNonNull( 76 ctx.getSystemService(PermissionManager.class), 77 "PermissionManager system service cannot be null"); 78 mPermissionUtils = new BtPermissionUtils(ctx); 79 } 80 81 @Override 82 @Nullable 83 public IBinder registerAdapter(@NonNull IBluetoothManagerCallback callback) { 84 requireNonNull(callback, "Callback cannot be null in registerAdapter"); 85 IBluetooth bluetooth = mBluetoothManagerService.registerAdapter(callback); 86 if (bluetooth == null) { 87 return null; 88 } 89 return bluetooth.asBinder(); 90 } 91 92 @Override 93 public void unregisterAdapter(@NonNull IBluetoothManagerCallback callback) { 94 requireNonNull(callback, "Callback cannot be null in unregisterAdapter"); 95 mBluetoothManagerService.unregisterAdapter(callback); 96 } 97 98 @Override 99 public boolean enable(@NonNull AttributionSource source) { 100 requireNonNull(source, "AttributionSource cannot be null in enable"); 101 102 final String errorMsg = 103 mPermissionUtils.callerCanToggle( 104 mContext, 105 source, 106 mUserManager, 107 mAppOpsManager, 108 mPermissionManager, 109 "enable", 110 true); 111 if (!errorMsg.isEmpty()) { 112 Log.d(TAG, "enable(): FAILED: " + errorMsg); 113 return false; 114 } 115 116 return mBluetoothManagerService.enable(source.getPackageName()); 117 } 118 119 @Override 120 public boolean enableNoAutoConnect(AttributionSource source) { 121 requireNonNull(source, "AttributionSource cannot be null in enableNoAutoConnect"); 122 123 final String errorMsg = 124 mPermissionUtils.callerCanToggle( 125 mContext, 126 source, 127 mUserManager, 128 mAppOpsManager, 129 mPermissionManager, 130 "enableNoAutoConnect", 131 false); 132 if (!errorMsg.isEmpty()) { 133 Log.d(TAG, "enableNoAutoConnect(): FAILED: " + errorMsg); 134 return false; 135 } 136 137 if (!BtPermissionUtils.isCallerNfc(getCallingAppId())) { 138 throw new SecurityException("No permission to enable Bluetooth quietly"); 139 } 140 141 return mBluetoothManagerService.enableNoAutoConnect(source.getPackageName()); 142 } 143 144 @Override 145 public boolean disable(AttributionSource source, boolean persist) { 146 requireNonNull(source, "AttributionSource cannot be null in disable"); 147 148 if (!persist) { 149 BtPermissionUtils.enforcePrivileged(mContext); 150 } 151 152 final String errorMsg = 153 mPermissionUtils.callerCanToggle( 154 mContext, 155 source, 156 mUserManager, 157 mAppOpsManager, 158 mPermissionManager, 159 "disable", 160 true); 161 if (!errorMsg.isEmpty()) { 162 Log.d(TAG, "disable(): FAILED: " + errorMsg); 163 return false; 164 } 165 166 return mBluetoothManagerService.disable(source.getPackageName(), persist); 167 } 168 169 @Override 170 public int getState() { 171 if (!isCallerSystem(getCallingAppId()) 172 && !mPermissionUtils.checkIfCallerIsForegroundUser(mUserManager)) { 173 Log.w(TAG, "getState(): UNAUTHORIZED. Report OFF for non-active and non system user"); 174 return BluetoothAdapter.STATE_OFF; 175 } 176 177 return mBluetoothManagerService.getState(); 178 } 179 180 @Override 181 @RequiresPermission(allOf = {BLUETOOTH_CONNECT, LOCAL_MAC_ADDRESS}) 182 public String getAddress(AttributionSource source) { 183 requireNonNull(source, "AttributionSource cannot be null in getAddress"); 184 185 if (!checkConnectPermissionForDataDelivery( 186 mContext, mPermissionManager, source, "getAddress")) { 187 return null; 188 } 189 190 if (!isCallerSystem(getCallingAppId()) 191 && !mPermissionUtils.checkIfCallerIsForegroundUser(mUserManager)) { 192 Log.w(TAG, "getAddress(): Not allowed for non-active and non system user"); 193 return null; 194 } 195 196 if (mContext.checkCallingOrSelfPermission(LOCAL_MAC_ADDRESS) != PERMISSION_GRANTED) { 197 // TODO(b/280890575): Throws a SecurityException instead 198 Log.w(TAG, "getAddress(): Client does not have LOCAL_MAC_ADDRESS permission"); 199 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 200 } 201 202 return mBluetoothManagerService.getAddress(); 203 } 204 205 @Override 206 @RequiresPermission(BLUETOOTH_CONNECT) 207 public String getName(AttributionSource source) { 208 requireNonNull(source, "AttributionSource cannot be null in getName"); 209 210 if (!checkConnectPermissionForDataDelivery( 211 mContext, mPermissionManager, source, "getName")) { 212 return null; 213 } 214 215 if (!isCallerSystem(getCallingAppId()) 216 && !mPermissionUtils.checkIfCallerIsForegroundUser(mUserManager)) { 217 Log.w(TAG, "getName(): not allowed for non-active and non system user"); 218 return null; 219 } 220 221 return mBluetoothManagerService.getName(); 222 } 223 224 @Override 225 @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) 226 public boolean onFactoryReset(AttributionSource source) { 227 requireNonNull(source, "AttributionSource cannot be null in onFactoryReset"); 228 229 BtPermissionUtils.enforcePrivileged(mContext); 230 231 if (!checkConnectPermissionForDataDelivery( 232 mContext, mPermissionManager, source, "onFactoryReset")) { 233 return false; 234 } 235 236 return mBluetoothManagerService.onFactoryReset(); 237 } 238 239 @Override 240 public boolean factoryReset() { 241 return true; 242 } 243 244 public boolean isBleScanAvailable() { 245 return mBluetoothManagerService.isBleScanAvailable(); 246 } 247 248 @Override 249 @RequiresPermission(BLUETOOTH_CONNECT) 250 public boolean enableBle(AttributionSource source, IBinder token) { 251 requireNonNull(source, "AttributionSource cannot be null in enableBle"); 252 requireNonNull(token, "IBinder cannot be null in enableBle"); 253 254 final String errorMsg = 255 mPermissionUtils.callerCanToggle( 256 mContext, 257 source, 258 mUserManager, 259 mAppOpsManager, 260 mPermissionManager, 261 "enableBle", 262 false); 263 if (!errorMsg.isEmpty()) { 264 Log.d(TAG, "enableBle(): FAILED: " + errorMsg); 265 return false; 266 } 267 268 return mBluetoothManagerService.enableBle(source.getPackageName(), token); 269 } 270 271 @Override 272 @RequiresPermission(BLUETOOTH_CONNECT) 273 public boolean disableBle(AttributionSource source, IBinder token) { 274 requireNonNull(source, "AttributionSource cannot be null in disableBle"); 275 requireNonNull(token, "IBinder cannot be null in disableBle"); 276 277 final String errorMsg = 278 mPermissionUtils.callerCanToggle( 279 mContext, 280 source, 281 mUserManager, 282 mAppOpsManager, 283 mPermissionManager, 284 "disableBle", 285 false); 286 if (!errorMsg.isEmpty()) { 287 Log.d(TAG, "disableBle(): FAILED: " + errorMsg); 288 return false; 289 } 290 291 return mBluetoothManagerService.disableBle(source.getPackageName(), token); 292 } 293 294 @Override 295 public boolean isHearingAidProfileSupported() { 296 return mBluetoothManagerService.isHearingAidProfileSupported(); 297 } 298 299 @Override 300 @RequiresPermission(BLUETOOTH_PRIVILEGED) 301 public int setBtHciSnoopLogMode(int mode) { 302 BtPermissionUtils.enforcePrivileged(mContext); 303 304 return mBluetoothManagerService.setBtHciSnoopLogMode(mode); 305 } 306 307 @Override 308 @RequiresPermission(BLUETOOTH_PRIVILEGED) 309 public int getBtHciSnoopLogMode() { 310 BtPermissionUtils.enforcePrivileged(mContext); 311 312 return mBluetoothManagerService.getBtHciSnoopLogMode(); 313 } 314 315 @Override 316 public int handleShellCommand( 317 @NonNull ParcelFileDescriptor in, 318 @NonNull ParcelFileDescriptor out, 319 @NonNull ParcelFileDescriptor err, 320 @NonNull String[] args) { 321 return new BluetoothShellCommand(mBluetoothManagerService) 322 .exec( 323 this, 324 in.getFileDescriptor(), 325 out.getFileDescriptor(), 326 err.getFileDescriptor(), 327 args); 328 } 329 330 @Override 331 @RequiresPermission(BLUETOOTH_PRIVILEGED) 332 public boolean isAutoOnSupported() { 333 BtPermissionUtils.enforcePrivileged(mContext); 334 return mBluetoothManagerService.isAutoOnSupported(); 335 } 336 337 @Override 338 @RequiresPermission(BLUETOOTH_PRIVILEGED) 339 public boolean isAutoOnEnabled() { 340 BtPermissionUtils.enforcePrivileged(mContext); 341 return mBluetoothManagerService.isAutoOnEnabled(); 342 } 343 344 @Override 345 @RequiresPermission(BLUETOOTH_PRIVILEGED) 346 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 347 public void setAutoOnEnabled(boolean status) { 348 BtPermissionUtils.enforcePrivileged(mContext); 349 mBluetoothManagerService.setAutoOnEnabled(status); 350 } 351 352 @Override 353 @RequiresPermission(DUMP) 354 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 355 if (mContext.checkCallingOrSelfPermission(DUMP) != PERMISSION_GRANTED) { 356 // TODO(b/280890575): Throws SecurityException instead 357 Log.w(TAG, "dump(): Client does not have DUMP permission"); 358 return; 359 } 360 361 mBluetoothManagerService.dump(fd, writer, args); 362 } 363 }
最新发布
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值