一、前言
很久没看到java内部类了,今天在审查代码时候,发现了java内部类,主要是内部类还嵌套了内部类。于是记录一下
二、java内部类的作用与优缺点
Java内部类,也称为嵌套类,是定义在另一个类(外部类)内部的类。内部类提供了将逻辑上相关的类组织在一起的方式,并增强了封装性。以下是内部类的主要作用及其优缺点:
内部类的作用:
封装性增强:内部类可以隐藏不希望从外部直接访问的类、成员变量或方法,从而增强了封装性。
代码组织:内部类可以将一些逻辑上紧密相关的类组织在一起,从而提高了代码的可读性和可维护性。
访问外部类的私有成员:内部类可以直接访问外部类的私有成员(包括私有字段、私有方法、私有内部类等),而无需通过getter或setter方法。
实现回调和事件处理:内部类常被用作回调和事件处理的机制,例如监听器接口的实现。
实现多继承:虽然Java不支持类的多继承,但可以通过内部类实现接口的多继承,从而间接实现多继承的效果。
内部类的优点:
提高代码的可读性和可维护性:通过将相关的类组织在一起,提高了代码的组织性和清晰度。
增加封装性:内部类可以限制对外部类的访问,进一步提高了封装性。
实现更灵活的设计:内部类可以实现一些特定的设计模式,如工厂模式、策略模式等,使代码更灵活。
内部类的缺点:
可读性下降:对于不熟悉内部类的人来说,阅读和理解代码可能会更加困难,因为内部类的结构相对复杂。
命名冲突:如果内部类与外部类或其他内部类具有相同的名称,可能会导致命名冲突和混淆。
内存消耗:由于内部类对象持有对外部类对象的隐式引用,因此可能会导致额外的内存消耗。
访问限制:静态内部类不能访问外部类的非静态成员,这可能会限制其用途。
匿名内部类的限制:匿名内部类虽然方便,但只能在定义时使用一次,且不能添加构造方法,这可能会限制其灵活性。
在使用内部类时,需要根据具体场景和需求权衡其优缺点,以做出合理的选择。
三、java内部类例子
其中里面就包含了内部类再嵌套内部类的做法,可阅读性非常差。
public class RequestOrderOperateModel {private Long operId;// 操作员IDprivate String operName;// 操作员名称private List orderOperate;// 订单操作 (批量)private String orderType; // 订单类型200001: 商城消费主订单200002: 支付订单200003: 库存订单200004: 配送订单private String filterStoreOuCode; // 店铺权限过滤private String filterStoreStandCode;// 店铺权限过滤 (标准编码)private Boolean autoPickup; // 是否超时自动提货private String refundRemark;// 退款原因private String refundContactPhone;// 退款联系电话@MethodAnnotation(description = "操作员ID")public Long getOperId() {return operId;}public void setOperId(Long operId) {this.operId = operId;}@MethodAnnotation(description = "操作员名称")public String getOperName() {return operName;}public void setOperName(String operName) {this.operName = operName;}@MethodAnnotation(description = "订单类型200001: 商城消费主订单200015: 支付订单200016: 库存订单200017: 配送订单")public String getOrderType() {return orderType;}public void setOrderType(String orderType) {this.orderType = orderType;}@MethodAnnotation(description = "订单操作 (批量)")public List getOrderOperate() {return orderOperate;}public void setOrderOperate(List orderOperate) {this.orderOperate = orderOperate;}@MethodAnnotation(description = "店铺权限过滤")public String getFilterStoreOuCode() {return filterStoreOuCode;}public void setFilterStoreOuCode(String filterStoreOuCode) {this.filterStoreOuCode = filterStoreOuCode;}@MethodAnnotation(description = "店铺权限过滤 (标准编码)")public String getFilterStoreStandCode() {return filterStoreStandCode;}public void setFilterStoreStandCode(String filterStoreStandCode) {this.filterStoreStandCode = filterStoreStandCode;}public Boolean getAutoPickup() {return autoPickup;}public void setAutoPickup(Boolean autoPickup) {this.autoPickup = autoPickup;}public String getRefundRemark() {return refundRemark;}public void setRefundRemark(String refundRemark) {this.refundRemark = refundRemark;}public String getRefundContactPhone() {return refundContactPhone;}public void setRefundContactPhone(String refundContactPhone) {this.refundContactPhone = refundContactPhone;}public static class OrderOperate {private Long orderId; // 订单IDprivate String userId;// 用户IDprivate Long deliveryOrderId; // 配送单IDprivate Long repairOrderId; // 售后单IDprivate String interfaceOrderId;// 第三方订单IDprivate Integer state;// 订单状态 (4待收货 6 拒收 9已完成 11已退款 12支付后取消 16待发货 17待备货)private String expressName; // 快递公司名称 (修改为发货状态时使用)private String expressCode; // 快递公司名称 (修改为发货状态时使用)private String expressNo; // 快递公司单号 (修改为发货状态时使用)private BigDecimal expressFreightAmount;// 快递配送运费金额private String pickupCode;// 提货码 (自提单修改为完成状态时使用)private List eleCode; // 电子码 (日期型商品 备货状态使用)private Date optime;// 发货/妥投/退货时间(yyyy-MM-dd HH:mm:ss)private String approvalBizLine; // 审核业务线条private String approvalOpinion; // 退款审核意见private List orderItemOperate;// 订单项操作 (批量)private Integer returnFreightFlag;// 是否退运费 1 退 0 不退(默认)private String thirdOrderState1;// 第三方系统订单状态(中免扫码购:牵牛花)private String thirdOrderState2;// 第三方系统订单状态(中免扫码购:eop)private String refundReason;// 退款原因private Long refundOrderId; // 退款单IDprivate Integer isActual; // 是否实物退款(0:否, 1:是)@MethodAnnotation(description = "订单ID")public Long getOrderId() {return orderId;}public void setOrderId(Long orderId) {this.orderId = orderId;}@MethodAnnotation(description = "用户ID")public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}@MethodAnnotation(description = "售后单ID")public Long getRepairOrderId() {return repairOrderId;}public void setRepairOrderId(Long repairOrderId) {this.repairOrderId = repairOrderId;}@MethodAnnotation(description = "配送单ID")public Long getDeliveryOrderId() {return deliveryOrderId;}public void setDeliveryOrderId(Long deliveryOrderId) {this.deliveryOrderId = deliveryOrderId;}@MethodAnnotation(description = "第三方订单ID")public String getInterfaceOrderId() {return interfaceOrderId;}public void setInterfaceOrderId(String interfaceOrderId) {this.interfaceOrderId = interfaceOrderId;}@MethodAnnotation(description = "订单状态 (4待收货 6 拒收 9已完成 11已退款 12支付后取消 16待发货 17待备货)")public Integer getState() {return state;}public void setState(Integer state) {this.state = state;}@MethodAnnotation(description = "快递公司名称 (修改为发货状态时使用)")public String getExpressName() {return expressName;}public void setExpressName(String expressName) {this.expressName = expressName;}@MethodAnnotation(description = "快递公司标准编码 (修改为发货状态时使用)")public String getExpressCode() {return expressCode;}public void setExpressCode(String expressCode) {this.expressCode = expressCode;}@MethodAnnotation(description = "快递公司单号 (修改为发货状态时使用)")public String getExpressNo() {return expressNo;}public void setExpressNo(String expressNo) {this.expressNo = expressNo;}@MethodAnnotation(description = "快递配送运费金额 (修改为发货状态时使用)")public BigDecimal getExpressFreightAmount() {return expressFreightAmount;}public void setExpressFreightAmount(BigDecimal expressFreightAmount) {this.expressFreightAmount = expressFreightAmount;}@MethodAnnotation(description = "提货码 (自提单修改为完成状态时使用)")public String getPickupCode() {return pickupCode;}public void setPickupCode(String pickupCode) {this.pickupCode = pickupCode;}@MethodAnnotation(description = "电子码 (日期型商品 备货状态使用)")public List getEleCode() {return eleCode;}public void setEleCode(List eleCode) {this.eleCode = eleCode;}@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@MethodAnnotation(description = "操作时间 (yyyy-MM-dd HH:mm:ss)")public Date getOptime() {return optime;}public void setOptime(Date optime) {this.optime = optime;}@MethodAnnotation(description = "审核业务线条")public String getApprovalBizLine() {return approvalBizLine;}public void setApprovalBizLine(String approvalBizLine) {this.approvalBizLine = approvalBizLine;}@MethodAnnotation(description = "退款审核意见")public String getApprovalOpinion() {return approvalOpinion;}public void setApprovalOpinion(String approvalOpinion) {this.approvalOpinion = approvalOpinion;}@MethodAnnotation(description = "订单项操作")public List getOrderItemOperate() {return orderItemOperate;}public void setOrderItemOperate(List orderItemOperate) {this.orderItemOperate = orderItemOperate;}@MethodAnnotation(description = "是否退运费 1 退 0 不退(默认)")public Integer getReturnFreightFlag() {return returnFreightFlag;}public void setReturnFreightFlag(Integer returnFreightFlag) {this.returnFreightFlag = returnFreightFlag;}@MethodAnnotation(description = "第三方系统订单状态:牵牛花订单状态")public String getThirdOrderState1() {return thirdOrderState1;}public void setThirdOrderState1(String thirdOrderState1) {this.thirdOrderState1 = thirdOrderState1;}@MethodAnnotation(description = "第三方系统订单状态:eop订单状态")public String getThirdOrderState2() {return thirdOrderState2;}public void setThirdOrderState2(String thirdOrderState2) {this.thirdOrderState2 = thirdOrderState2;}@MethodAnnotation(description = "退款原因")public String getRefundReason() {return refundReason;}public void setRefundReason(String refundReason) {this.refundReason = refundReason;}public Long getRefundOrderId() {return refundOrderId;}public void setRefundOrderId(Long refundOrderId) {this.refundOrderId = refundOrderId;}public Integer getIsActual() {return isActual;}public void setIsActual(Integer isActual) {this.isActual = isActual;}public static class OrderItemOperate{private Long orderItemId; // 订单项IDprivate Long skuId; // 商品Idprivate Integer number; // 商品数量private BigDecimal thirdPoints; // 分摊的thirdPoints(大会员积分需要从大会员接口获取,走埋点取,内部辅助使用)private String storeOuCode; // 店铺编码private String refundReason;// 退款原因private String refundContactPhone;// 退款联系电话public Long getOrderItemId() {return orderItemId;}public void setOrderItemId(Long orderItemId) {this.orderItemId = orderItemId;}public Long getSkuId() {return skuId;}public void setSkuId(Long skuId) {this.skuId = skuId;}public Integer getNumber() {return number;}public void setNumber(Integer number) {this.number = number;}public BigDecimal getThirdPoints() {return thirdPoints;}public void setThirdPoints(BigDecimal thirdPoints) {this.thirdPoints = thirdPoints;}public String getStoreOuCode() {return storeOuCode;}public void setStoreOuCode(String storeOuCode) {this.storeOuCode = storeOuCode;}public String getRefundReason() {return refundReason;}public void setRefundReason(String refundReason) {this.refundReason = refundReason;}public String getRefundContactPhone() {return refundContactPhone;}public void setRefundContactPhone(String refundContactPhone) {this.refundContactPhone = refundContactPhone;}}}}
四、避免过多使用内部类
尽管内部类在Java中是一种强大的工具,可以提供封装性、代码组织性和灵活性,但在某些情况下,使用内部类可能不是最佳选择。以下是一些建议,以帮助你在Java中避免不必要地使用内部类:
保持简单性:如果你的类结构变得复杂,并且开始过度依赖内部类,那么考虑是否可以通过简化设计来避免使用内部类。例如,你可以将内部类的功能移动到外部类中,或者通过接口和委托来解耦代码。
避免隐藏逻辑:内部类可能会隐藏一些重要的逻辑,使得其他开发者难以理解和维护代码。如果内部类的主要作用是封装某个特定逻辑,而该逻辑对于外部类或其他开发者来说很重要,那么最好将该逻辑提取到单独的外部类中。
考虑性能开销:内部类对象会持有对外部类对象的隐式引用,这可能导致额外的内存消耗。如果你的应用程序对性能有严格要求,并且你发现内部类导致了不必要的性能开销,那么可能需要重新考虑你的设计。
避免命名冲突:内部类和外部类或其他内部类之间可能存在命名冲突。为了避免这种情况,你可以使用更具描述性的类名,或者将内部类移动到单独的包中。然而,如果这样做导致代码结构变得复杂,那么可能需要重新考虑是否应该使用内部类。
替代方案:有时候,你可以使用其他Java特性来替代内部类。例如,你可以使用接口和匿名类来实现回调机制;使用静态方法或工具类来提供实用功能;使用组合(has-a关系)而不是继承(is-a关系)来组织类之间的关系。
文档和注释:如果你决定使用内部类,确保为你的代码提供充分的文档和注释。解释内部类的目的、用法和与外部类之间的关系,以帮助其他开发者理解你的代码。
总之,虽然内部类在某些情况下非常有用,但在其他情况下可能会增加代码的复杂性和维护成本。因此,在决定是否使用内部类时,请权衡其优缺点,并根据具体需求做出合理的选择。