如何优雅规范编写Java代码

编码规范

我们为什么要遵守规范来编码?

是因为通常在编码过程中我们不只自己进行开发,通常需要一个团队来进行,开发好之后还需要维护,所以编码规范就显的尤为重要。

代码维护时间比较长,那么保证代码可读性就显得很重要。作为一个程序员,咱们得有点追求和信仰。推荐《阿里巴巴Java开发手册》

代码结构

编写代码最终要的原则就是要具有扩展性,如果没有扩展性那么代码维护起来会非常麻烦。

优雅判空

使用Spring提供的工具类Assert判空
public class MyTest {
    public static void main(String[] args) {
        Object obj = new Object();
        Assert.notNull(obj,"对象不能为空");
        Assert.isTrue(obj != null,"对象不能为空");
        ArrayList<Object> list = new ArrayList<>();
        Assert.notEmpty(list,"list不能为空");
    }
}
使用Java8链式调用特性判空
public class MyTest {
    public static void main(String[] args) {
        Object obj = new Object();
        System.out.println("是否不为空:" + Optional.of(obj).isPresent());

        User user = new User();
        user.setId(1);
        user.setName("ls");
        Optional<User> zs = Optional.of(user).filter(u -> u.getName().equals("zs"));
        System.out.println(zs.get());
        zs.ifPresent(item ->{
             System.out.println("对象不等于空,做的一系列操作");
         });
        User user1 = Optional.of(zs.orElse(new User())).get();
        System.out.println(user1);
    }


    static class User {
        private int id;
        private String name;

        public String getName() {
            return name;
        }
        public int getId() {
            return id;
        }
        public void setName(String name) {
            this.name = name;
        }
        public void setId(int id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
}

自定义链式调用,对Optional扩展:

  • https://www.hollischuang.com/archives/5605
@Data
public class User {

    private String name;

    private String gender;

    private School school;

    @Data
    public static class School {

        private String scName;

        private String adress;
    }
}
/**
* @author Axin
* @since 2020-09-10
* @summary 链式调用 bean 中 value 的方法
*/
public final class OptionalBean<T> {

    private static final OptionalBean<?> EMPTY = new OptionalBean<>();

    private final T value;

    private OptionalBean() {
        this.value = null;
    }

    /**
     * 空值会抛出空指针
     * @param value
     */
    private OptionalBean(T value) {
        this.value = Objects.requireNonNull(value);
    }

    /**
     * 包装一个不能为空的 bean
     * @param value
     * @param <T>
     * @return
     */
    public static <T> OptionalBean<T> of(T value) {
        return new OptionalBean<>(value);
    }

    /**
     * 包装一个可能为空的 bean
     * @param value
     * @param <T>
     * @return
     */
    public static <T> OptionalBean<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    /**
     * 取出具体的值
     * @param fn
     * @param <R>
     * @return
     */
    public T get() {
        return Objects.isNull(value) ? null : value;
    }

    /**
     * 取出一个可能为空的对象
     * @param fn
     * @param <R>
     * @return
     */
    public <R> OptionalBean<R> getBean(Function<? super T, ? extends R> fn) {
        return Objects.isNull(value) ? OptionalBean.empty() : OptionalBean.ofNullable(fn.apply(value));
    }

    /**
     * 如果目标值为空 获取一个默认值
     * @param other
     * @return
     */
    public T orElse(T other) {
        return value != null ? value : other;
    }

    /**
     * 如果目标值为空 通过lambda表达式获取一个值
     * @param other
     * @return
     */
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    /**
     * 如果目标值为空 抛出一个异常
     * @param exceptionSupplier
     * @param <X>
     * @return
     * @throws X
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    public boolean isPresent() {
        return value != null;
    }

    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    /**
     * 空值常量
     * @param <T>
     * @return
     */
    public static<T> OptionalBean<T> empty() {
        @SuppressWarnings("unchecked")
        OptionalBean<T> none = (OptionalBean<T>) EMPTY;
        return none;
    }

}
public static void main(String[] args) {

    User axin = new User();
    User.School school = new User.School();
    axin.setName("hello");

    // 1. 基本调用
    String value1 = OptionalBean.ofNullable(axin)
            .getBean(User::getSchool)
            .getBean(User.School::getAdress).get();
    System.out.println(value1);

    // 2. 扩展的 isPresent方法 用法与 Optional 一样
    boolean present = OptionalBean.ofNullable(axin)
            .getBean(User::getSchool)
            .getBean(User.School::getAdress).isPresent();
    System.out.println(present);


    // 3. 扩展的 ifPresent 方法
    OptionalBean.ofNullable(axin)
            .getBean(User::getSchool)
            .getBean(User.School::getAdress)
            .ifPresent(adress -> System.out.println(String.format("地址存在:%s", adress)));

    // 4. 扩展的 orElse
    String value2 = OptionalBean.ofNullable(axin)
            .getBean(User::getSchool)
            .getBean(User.School::getAdress).orElse("家里蹲");

    System.out.println(value2);

    // 5. 扩展的 orElseThrow
    try {
        String value3 = OptionalBean.ofNullable(axin)
                .getBean(User::getSchool)
                .getBean(User.School::getAdress).orElseThrow(() -> new RuntimeException("空指针了"));
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}
使用BeanValidator注解判空

思路:定义一个注解,将需要校验的参数对象都标注该注解,利用SpringAOP,拦截该注解,将其中标注的参数取出,最后通过BeanValidator进行校验。

所需依赖:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
/**
 * facade接口注解, 用于统一对facade进行参数校验及异常捕获
 * @author whitepure
 */
@Target({ElementType.METHOD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Facade {

}
@Slf4j
@Aspect
@Component
public class FacadeAspect {


    @Around("@annotation(com.spring.example.annotation.Facade)")
    public Object facade(ProceedingJoinPoint pjp) throws Exception {

        // 获取,执行目标方法
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();

        Object[] args = pjp.getArgs();

        log.info("获取@Facede注解参数列表,参数: {}", args);

        // 参数类型
        Class<?> returnType = ((MethodSignature) pjp.getSignature()).getMethod().getReturnType();

        //循环遍历所有参数,进行参数校验
        for (Object parameter : args) {
            try {
                BeanValidator.validateObject(parameter);
            } catch (ValidationException e) {
                return getFailedResponse(returnType, e);
            }
        }

        try {
            // 目标方法执行
            return pjp.proceed();
        } catch (Throwable throwable) {
            // 返回通用失败响应
            return getFailedResponse(returnType, throwable);
        }
    }

    /**
     * 定义并返回一个通用的失败响应
     */
    private Object getFailedResponse(Class<?> returnType, Throwable throwable)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //如果返回值的类型为BaseResponse 的子类,则创建一个通用的失败响应
        if (returnType.getDeclaredConstructor().newInstance() instanceof ApiResponse) {
            ApiResponse response = (ApiResponse) returnType.getDeclaredConstructor().newInstance();
            String message = throwable.getMessage();
            log.error("校验bean异常:", throwable);
            response.setMessage(message);
            response.setCode(Status.ERROR.getCode());
            return response;
        }
        log.error("failed to getFailedResponse , returnType ({}) is not instanceof BaseResponse", returnType);
        return null;
    }

}
public class BeanValidator {


    private static final Validator validator = Validation
            .byProvider(HibernateValidator.class)
            .configure().failFast(true)
            .buildValidatorFactory().getValidator();

    /**
     * 校验对象
     *
     * @param object object
     * @param groups groups
     */
    public static void validateObject(Object object, Class<?>... groups) throws ValidationException {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (constraintViolations.stream().findFirst().isPresent()) {
            throw new ValidationException(constraintViolations.stream().findFirst().get().getMessage());
        }
    }


    /**
     * 校验对象bean
     *
     * @param t      bean
     * @param groups 校验组
     * @return ValidResult
     */
    public static <T> ValidResult validateBean(T t, Class<?>... groups) {
        ValidResult result = new ValidResult();
        Set<ConstraintViolation<T>> violationSet = validator.validate(t, groups);
        boolean hasError = violationSet != null && violationSet.size() > 0;
        result.setHasErrors(hasError);
        if (hasError) {
            for (ConstraintViolation<T> violation : violationSet) {
                result.addError(violation.getPropertyPath().toString(), violation.getMessage());
            }
        }
        return result;
    }

    /**
     * 校验bean的某一个属性
     *
     * @param obj          bean
     * @param propertyName 属性名称
     * @return ValidResult
     */
    public static <T> ValidResult validateProperty(T obj, String propertyName) {
        ValidResult result = new ValidResult();
        Set<ConstraintViolation<T>> violationSet = validator.validateProperty(obj, propertyName);
        boolean hasError = violationSet != null && violationSet.size() > 0;
        result.setHasErrors(hasError);
        if (hasError) {
            for (ConstraintViolation<T> violation : violationSet) {
                result.addError(propertyName, violation.getMessage());
            }
        }
        return result;
    }

    /**
     * 校验结果类
     */
    @Data
    public static class ValidResult {

        /**
         * 是否有错误
         */
        private boolean hasErrors;

        /**
         * 错误信息
         */
        private List<ErrorMessage> errors;

        public ValidResult() {
            this.errors = new ArrayList<>();
        }

        public boolean hasErrors() {
            return hasErrors;
        }

        public void setHasErrors(boolean hasErrors) {
            this.hasErrors = hasErrors;
        }

        /**
         * 获取所有验证信息
         *
         * @return 集合形式
         */
        public List<ErrorMessage> getAllErrors() {
            return errors;
        }

        /**
         * 获取所有验证信息
         *
         * @return 字符串形式
         */
        public String getErrors() {
            StringBuilder sb = new StringBuilder();
            for (ErrorMessage error : errors) {
                sb.append(error.getPropertyPath()).append(":").append(error.getMessage()).append(" ");
            }
            return sb.toString();
        }

        public void addError(String propertyName, String message) {
            this.errors.add(new ErrorMessage(propertyName, message));
        }
    }

    @Data
    public static class ErrorMessage {

        private String propertyPath;

        private String message;

        public ErrorMessage() {
        }

        public ErrorMessage(String propertyPath, String message) {
            this.propertyPath = propertyPath;
            this.message = message;
        }
    }

}

过多if…else

替换if…else并不会降低代码的复杂度,相反比较少见的写法可能会增加认知负荷,从而进一步增加了复杂度。之所以要替换过多的if…else是为了对代码进行解耦合,方便扩展代码,最终方便对代码的维护。

以下有几种常见的方法来替换过多的if…else。

使用枚举代替if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "FOUR";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
        ConditionEnum conditionEnum;
        try {
            conditionEnum = ConditionEnum.valueOf(val);
        } catch (IllegalArgumentException e) {
            System.out.println("val:" + val);
            return;
        }
        exec(conditionEnum);
    }

    public static void exec(ConditionEnum conditionEnum) {
        conditionEnum.context();
    }

    enum ConditionEnum {
        ONE {
            @Override
            public void context() {
                System.out.println("val:" + 1111111);
            }
        },
        TWO {
            @Override
            public void context() {
                System.out.println("val:" + 2222222);
            }
        },
        THREE {
            @Override
            public void context() {
                System.out.println("val:" + 3333333);
            }
        };

        public abstract void context();
    }

}

也可用枚举替换成这样:

    public static void newCondition(String val) {
        ConditionEnum condition = ConditionEnum.getCondition(val);
        System.out.println("val:" + (condition == null ? val : condition.value));
    }

    enum ConditionEnum {
        ONE("ONE",1111111),
        TWO("TWO",2222222),
        THREE("THREE",3333333)

        ;

        private String key;
        private Integer value;

        ConditionEnum(String key,Integer value){
            this.key = key;
            this.value = value;
        }

        public  static ConditionEnum getCondition(String key){
            return Arrays.stream(ConditionEnum.values()).filter(x -> Objects.equals(x.key, key)).findFirst().orElse(null);
        }
    }
放入数据结构中进行判断从而减少if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "1";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }
    public static void condition(String val) {
        if ("1".equals(val)){
            System.out.println("val:" + 1111111);
        }else if ("2".equals(val)){
            System.out.println("val:" + 2222222);
        }else if ("3".equals(val)){
            System.out.println("val:" + 3333333);
        }else {
            System.out.println("val:" + val);
        }
    }
    public static void newCondition(String val){
        Map<String, Function<?,?>> map = new HashMap<>();
        map.put("1",(action) -> 1111111);
        map.put("2",(action) -> 2222222);
        map.put("3",(action) -> 3333333);
        System.out.println("val:" + (map.get(val) != null ? map.get(val).apply(null) : val));
    }

}
使用switch…case代替if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "FOUR";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
        switch (val) {
            case "ONE":
                System.out.println("val:" + 1111111);
                break;
            case "TWO":
                System.out.println("val:" + 2222222);
                break;
            case "THREE":
                System.out.println("val:" + 3333333);
                break;
            default:
                System.out.println("val:" + val);
        }
    }
}
尽早结束if使代码结构更清晰
public class MyTest {
    public static void main(String[] args) {
        String val = "222";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
            return;
        }
        if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
            return;
        }
        if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
            return;
        }
        System.out.println("val:" + val);
    }
}
使用职责链模式代替if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "1";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
        One one = new One();
        Two two = new Two();
        Three three = new Three();

        // 设置调用链,可设置成死循环
        one.setAbstractHandler(two);
        two.setAbstractHandler(three);

        // 执行
        one.exec(val);
    }
}

abstract class AbstractHandler {

    protected AbstractHandler abstractHandler;

    protected void setAbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }

    protected abstract void exec(String val);

}

class One extends AbstractHandler {

    @Override
    protected void exec(String val) {
        if (!val.equals("ONE")){
            abstractHandler.exec(val);
            return;
        }
        System.out.println("val:" + 1111111);
    }
}

class Two extends AbstractHandler {

    @Override
    protected void exec(String val) {
        if (!val.equals("TWO")){
            abstractHandler.exec(val);
            return;
        }
        System.out.println("val:" + 2222222);
    }
}

class Three extends AbstractHandler {

    @Override
    protected void exec(String val) {
        System.out.println(val.equals("THREE") ? "val:" + 3333333 : "val:" + val);
    }
}
使用模板方法模式代替if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "ONE";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
        if (!Objects.equals(val, "ONE") && !Objects.equals(val, "TWO") && !Objects.equals(val, "THREE")) {
            System.out.println("val:" + val);
            return;
        }
        List<ConditionTemplate> list = new ArrayList<>(Arrays.asList(new One(), new Two(), new Three()));
        for (ConditionTemplate item : list) {
            item.template(val);
        }
    }

}

abstract class ConditionTemplate {

    public void template(String val){
        if (supportIns(val)){
            support();
        }
    }

    public abstract void support();

    public abstract boolean supportIns(String val);

}

class One extends ConditionTemplate {
    @Override
    public void support() {
        System.out.println("val:" + 1111111);
    }
    @Override
    public boolean supportIns(String val) {
        return "ONE".equals(val);
    }
}

class Two extends ConditionTemplate {
    @Override
    public void support() {
        System.out.println("val:" + 2222222);
    }
    @Override
    public boolean supportIns(String val) {
        return "TWO".equals(val);
    }
}

class Three extends ConditionTemplate {
    @Override
    public void support() {
        System.out.println("val:" + 3333333);
    }
    @Override
    public boolean supportIns(String val) {
        return "THREE".equals(val);
    }
}
使用工厂方法模式代替if…else
public class MyTest {
    public static void main(String[] args) {
        String val = "ONE";
        condition(val);
        System.out.println("--------------");
        newCondition(val);
    }

    public static void condition(String val) {
        if ("ONE".equals(val)) {
            System.out.println("val:" + 1111111);
        } else if ("TWO".equals(val)) {
            System.out.println("val:" + 2222222);
        } else if ("THREE".equals(val)) {
            System.out.println("val:" + 3333333);
        } else {
            System.out.println("val:" + val);
        }
    }

    public static void newCondition(String val) {
         Map<String, ConditionFactory> operationMap = new HashMap<>();
        operationMap.put("ONE",new One());
        operationMap.put("TWO",new Two());
        operationMap.put("THREE",new Three());
        if (operationMap.get(val) == null) {
            System.out.println("val:" + val);
        }else {
            operationMap.get(val).printCondition();
        }
    }

}

interface ConditionFactory{
    void printCondition();
}

class One implements ConditionFactory {
    @Override
    public void printCondition() {
        System.out.println("val:" + 1111111);
    }
}

class Two implements ConditionFactory {
    @Override
    public void printCondition() {
        System.out.println("val:" + 2222222);
    }
}

class Three implements ConditionFactory {
    @Override
    public void printCondition() {
        System.out.println("val:" + 3333333);
    }
}
使用注解代替if…else
  • https://www.zhihu.com/question/318511891/answer/1730548947
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE)  
public @interface PayCode {  

     String value();    
     String name();  
}
@PayCode(value = "alia", name = "支付宝支付")  
@Service
public class AliaPay implements IPay {  

     @Override
     public void pay() {  
         System.out.println("===发起支付宝支付===");  
     }  
}  


@PayCode(value = "weixin", name = "微信支付")  
@Service
public class WeixinPay implements IPay {  

     @Override
     public void pay() {  
         System.out.println("===发起微信支付===");  
     }  
} 


@PayCode(value = "jingdong", name = "京东支付")  
@Service
public class JingDongPay implements IPay {  

     @Override
     public void pay() {  
        System.out.println("===发起京东支付===");  
     }  
}
@Service
public class PayService2 implements ApplicationListener<ContextRefreshedEvent> {  

     private static Map<String, IPay> payMap = null;  

     @Override
     public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {  
         ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();  
         Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);  

         if (beansWithAnnotation != null) {  
             payMap = new HashMap<>();  
             beansWithAnnotation.forEach((key, value) ->{  
                 String bizType = value.getClass().getAnnotation(PayCode.class).value();  
                 payMap.put(bizType, (IPay) value);  
             });  
         }  
     }  

     public void pay(String code) {  
        payMap.get(code).pay();  
     }  
}
  • 36
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我为您编写一段Java业务代码,该代码旨在展示代码优雅规范性、可读性、扩展性和可用性。 假设我们正在开发一个电商网站,以下是一个简单的购物车类的实现: ``` public class ShoppingCart { private Map<Product, Integer> cartItems; public ShoppingCart() { cartItems = new HashMap<>(); } public void addItem(Product product, int quantity) { if (cartItems.containsKey(product)) { int currentQuantity = cartItems.get(product); cartItems.put(product, currentQuantity + quantity); } else { cartItems.put(product, quantity); } } public void removeItem(Product product) { cartItems.remove(product); } public void updateItemQuantity(Product product, int quantity) { cartItems.put(product, quantity); } public int getTotalItems() { int total = 0; for (int quantity : cartItems.values()) { total += quantity; } return total; } public double getTotalPrice() { double totalPrice = 0; for (Map.Entry<Product, Integer> entry : cartItems.entrySet()) { Product product = entry.getKey(); int quantity = entry.getValue(); totalPrice += product.getPrice() * quantity; } return totalPrice; } } ``` 上述代码具有以下特点: - 代码规范代码采用了驼峰命名法,缩进对齐清晰明了,符合Java编码规范。 - 可读性:方法名、变量名都有明确的含义,易于理解代码的功能。注释清晰明了,代码结构简洁明了。 - 扩展性:如果需要添加新的功能,只需添加新的方法即可。例如,如果需要支持优惠券,则可以添加一个方法来计算折扣后的价格。 - 可用性:代码实现了购物车的基本功能,易于集成到网站中使用。同时,代码使用了Java集合类库,具有较高的性能和可靠性。 综上所述,该代码体现了编码能力的优雅规范性、可读性、扩展性和可用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值