Optional的详细实战用法,优雅的消除if..else..复杂逻辑运算函数封装....

如何优雅的消除if…else…让代码看起来高大上?兄弟们搞起来啊


怎么优雅的让你的代码不再有if…else;如何优雅的躲避深恶痛绝的NPE,这也许是一个程序员一生的追求,今天给大家带来一个案例,将一个臃肿的胖子,P成一个高富帅的过程.
其中使用到了J8的Optional这个容器.当然肯定有小伙伴比我用的好,或者比我理解的更透彻,我写的有不对的地方,也请小伙伴指出来,大家共同学习,共同进步…

if(我是高富帅){
	System.out("对象排排站")
}else{
	System.out("苦逼的写代码")
}

不叨逼叨逼叨了.先给大家看段代码,你若不晕,我连吹两瓶二锅头…

public class DiscountedPriceConverter implements CustomConverter {
    @Override
    public Object convert(Object destination, Object source, Class<?> destinationClass, Class<?> sourceClass) {
        double platformDiscount = 0;
        if (ObjectUtil.isEmpty(source)) {
            return String.valueOf(platformDiscount);
        }
        if (ObjectUtil.isNotEmpty(source) && source instanceof List) {
            List<?> objectList = (List<?>) source;
            Optional<?> optional = objectList.stream().findFirst();
            if (optional.isPresent()) {
                Object object = optional.get();
                if (object instanceof CouponDetail) {
                    List<CouponDetail> couponDetails =
                            ListsUtil.castList(source, CouponDetail.class);
                    if (ObjectUtil.isNotEmpty(couponDetails)) {
                        assert couponDetails != null;
                        for (CouponDetail couponDetail : couponDetails) {
                            if (ObjectUtil.isEmpty(couponDetail)) {
                                platformDiscount = 0;
                            }
                            if (ObjectUtil.isNotEmpty(couponDetail) && ObjectUtil.isNotEmpty(couponDetail.getCouponPrice())) {
                                platformDiscount += Double.parseDouble(couponDetail.getCouponPrice());
                            }
                        }
                        return String.valueOf(platformDiscount);
                    }
                }

                if (object instanceof com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enGet
                        .CouponDetail) {
                    List<com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enGet
                            .CouponDetail> couponDetails =
                            ListsUtil.castList(source, com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enGet
                                    .CouponDetail.class);
                    if (ObjectUtil.isNotEmpty(couponDetails)) {
                        assert couponDetails != null;
                        for (com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enGet
                                .CouponDetail couponDetail : couponDetails) {
                            if (ObjectUtil.isEmpty(couponDetail)) {
                                platformDiscount = 0;
                            }
                            if (ObjectUtil.isNotEmpty(couponDetail) && ObjectUtil.isNotEmpty(couponDetail.getCouponPrice())) {
                                platformDiscount += Double.parseDouble(couponDetail.getCouponPrice());
                            }
                        }
                        return String.valueOf(platformDiscount);
                    }
                }
            }
            return String.valueOf(platformDiscount);
        }
        return String.valueOf(platformDiscount);
    }
}

看了这段代码,如果你看到这段代码,如果没有反胃的生理反应,那么恭喜你,蓝翔挖掘机专业是你改变人生的最好途径.接下来,咱们就改造这个代码,让他看起来高大上…(这段没有注释的代码)

  1. 业务梳理

①、首先我们先看这里的大框架,是由两个两个逻辑块, 判空逻辑; 如果source为空则返回默认值,如果source不为空则返回计算后的值。
②、当source不为空时,需要判断source的类型是否为List类型,若不是则直接返回默认值.(这里受业务约束,必须是list)
③、当source为list且不为空时,要确定list中的泛型(这里受业务约束,list中的泛型为同一泛型,不存在多种类型同时存在的情况)
④、当source不为空时,这里执行了两个业务逻辑判断,也就是下面两个类的判断,两个类走了不同转换逻辑.否则返回默认值

com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enGet.CouponDetail
com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.search.CouponDetail
  1. 代码构建

通过对代码结构逻辑的梳理我们就可以着手改造这段代码了,首先我们先把大的框架写出来,在进行具体业务的逻辑处理

//这里为空则返回空对象 这里表示 如果source不为空则继续执行,若为空直接返回默认值
Optional.ofNullable(source)
		 //若source为list类型,这继续执行,若不为list类型则直接返回默认值
         .filter(fSource -> fSource instanceof List)
         //若source为list类型执行计算
         .map(mSource -> {
             //这里进行计算或者下一步逻辑
         })
         //这里返回默认值
         .orElse(String.valueOf(platformDiscount));

由上面代码可以看出这段逻辑代码的框架逻辑我们就已经搭建好了,下面对代码进行技术分析:(看黑板)

2.1、由于不知道source是否为空,这里使用ofNullable(),进行Optional的创建。Optional有三种实例化的方式:

①创建空Optional对象 empty();
②创建非空Optional对象,of();这里的容器中的对象一定不能为空,否者会抛出异常;
③创建非空或空Optional对象,ofNullable();

2.2、使用filter()进行source对象是否是List集合; filter()条件判断,返回optional容器,若结果为true则返回带有对象的Optional容器,否则返回空容器;

2.3、使用map()对内部细节业务逻辑进行计算;这里不对map()方法进行详细分析了,网上有很多资料,大家可以自己去看;这里给大家总结几点重要的点:(看黑板)

①map()接收的是上一层逻辑返回的容器中的对象值(类型),都必须一致;否则无法使用map()方法
②map()方法是主动为传递过来的对象创建Optional容器的,这跟flatMap()方法又却别;
③map()方法首先对容器内的对象进行判断,若对象为空,则直接返回空的Optional容器对象,若不为空,则直接将计算后的值重新创建新的Optional容器进行返回

2.4、orElse()方法返回默认值,Optional中的这个方法,就可以认为这个方法就是返回默认值的,可以理解为,如果为空,则直接返回默认值,不为空,则返回计算值;(这里需要强调,orElse()方法,在执行逻辑中,始终都是执行的,不管你当前Optional容器中的对象是不是空的,都会执行orElse()方法中的逻辑;如果为空执行,不为空不执行,需要使用orElseGet()方法);


接下来我们填充细节逻辑:

//这里为空则返回空对象 这里表示 如果source不为空则继续执行,若为空直接返回默认值
Optional.ofNullable(source)
		 //若source为list类型,这继续执行,若不为list类型则直接返回默认值
         .filter(fSource -> fSource instanceof List)
         //若source为list类型执行计算
         .map(mSource -> {
         	//这里确定source为list类型,则直接强转list,因为不确定泛型,所以用?来表示
             List<?> objectList = (List<?>) source;
			//取出list的第一个元素,这里无法得知,list中的元素是否为空,
			//或者其元素的中的属性值是否为空,所以还需要使用Optional容器进行规避NPE,
			//findFirst()方法返回的就是一个Optional容器 所以我们直接使用Map进行计算
			return objectList
                    .stream()
                    .findFirst()
                    //此时map中的firstSource为list中的第一条元素对象;
                    .map(firstSource ->
                    //这里需要强调,由于Optional中的对象不能同级进行传递,上面技术分析中有说到这一点;                            
                    	FunctionBuilder
                                    //创建IF函数实例
                                    .returnIf(new HashMap<Object, FunctionReturn<String>>())
                                    //添加函数条件以及执行函数
                                    .addReturn(CouponDetail.class, () -> ifSearchCouponDetail(source))
                                    //添加函数条件以及执行函数
                                    .addReturn(com.jd.open.api.sdk.domain.order
                                            .OrderQueryJsfService.response.enGet
                                            .CouponDetail.class, () -> ifEnGetCouPonDetail(source))
                                    //实际入参对象
                                    .doIfInstance(firstSource)
                                    //默认值
                                    .defaultValue(null)
                    ).orElse(null);
         })
         //这里返回默认值
         .orElse(String.valueOf(platformDiscount));

将具体的业务代码抽离成方法.

ifEnGetCouPonDetail(),如果是EnGetCouPonDetail类型走此方法执行业务
ifSearchCouponDetail(),如果是SearchCouponDetail类型的走此方法执行业务

   @NotNull
    private String ifEnGetCouPonDetail(Object source) {
        List<com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.
                enGet.CouponDetail> couponDetails =
                ListsUtil.castList(source, com.jd.open.api.sdk.domain.order.
                        OrderQueryJsfService.response.enGet.CouponDetail.class);
        double optionalDiscount = 0.0;
        for (com.jd.open.api.sdk.domain.order
                .OrderQueryJsfService.response.enGet
                .CouponDetail couponDetail : couponDetails) {
            optionalDiscount += Optional.ofNullable(couponDetail)
                    .map(com.jd.open.api.sdk.domain.order.OrderQueryJsfService.
                            response.enGet.CouponDetail::getCouponPrice)
                    .map(Double::parseDouble)
                    .orElse(optionalDiscount);
        }
        return String.valueOf(optionalDiscount);
    }
 @NotNull
    private String ifSearchCouponDetail(Object source) {
        List<CouponDetail> couponDetails =
                ListsUtil.castList(source, CouponDetail.class);
        double optionalDiscount = 0.0;
        for (CouponDetail couponDetail : couponDetails) {
            optionalDiscount += Optional.ofNullable(couponDetail)
                    .map(CouponDetail::getCouponPrice)
                    .map(Double::parseDouble)
                    .orElse(optionalDiscount);
        }
        return String.valueOf(optionalDiscount);
    }

对以上代码技术点进行分析:

在以上代码看来.逻辑清晰,结构简单,可阅读性强;这里重点说一下FunctionBuilder这个函数逻辑运算,这里是我自己封装的复杂逻辑运算的执行器,这里不能完全使用Optional来消除if,原因有两点如下:

①、Optional只能对容器中的对象是否为空,做为条件进行逻辑计算,但不能对其他条件逻辑进行判断
②、Optional对同级逻辑是不能使用同一个对象的, 比如你使用了两个map()方法,第一个map中是User对象,第二个map()方法中的Optional容器中的对象是第一个map(),计算后返回的对象,不可能是同一个User对象了,很明显不符合这里的业务逻辑;


这里我也贴出封装的部分源码

FunctionBuilder类

/**
 * @Author: yangjiahui
 * @Description: TODO  构建if函数的创建工具类
 * @Date: 2021/03/22 14:15
 */
public class FunctionBuilder {
    /**
     * 创建无返回值if函数
     *
     * @param map Map<条件,执行函数>
     * @param <K> 条件参数类型
     * @return if函数实例
     * @see Map
     */
    public static <K> IfVoidFunction<K> voidIf(Map<K, Function> map) {
        return IfVoidFunction.<K>builder().buildVoidIf(map).build();
    }

    public static <K, T> IfFunctionReturn<K, T> returnIf(Map<K, FunctionReturn<T>> returnMap) {
        return IfFunctionReturn.<K, T>builder().buildReturnIf(returnMap).build();
    }
}

IfFunctionReturn类

这里是带有返回值的if函数

/**
 * @Author: yangjiahui
 * @Description: TODO 带有返回值的if函数实例
 * @Date: 2021/03/05 5:43 下午
 */
public class IfFunctionReturn<K, T> {

    private Map<K, FunctionReturn<T>> mapReturn;

    /**
     * 如果不为null,则为该值;
     * 否则为false。如果为null,则表示不存在任何值
     */
    private T result;


    public void setMap(Map<K, FunctionReturn<T>> mapReturn) {
        this.mapReturn = mapReturn;
    }

    public IfFunctionReturn() {
    }

    /**
     * 添加条件 有返回值函数
     *
     * @param key            需要验证的条件(key)
     * @param functionReturn 要执行的方法
     * @return this.
     */
    public IfFunctionReturn<K, T> addReturn(K key, FunctionReturn<T> functionReturn) {
        this.mapReturn.put(key, functionReturn);
        return this;
    }

    /**
     * 批量添加条件 有返回值函数
     *
     * @param key            需要验证的条件(key)
     * @param functionReturn 要执行的方法
     * @return this.
     */
    @SafeVarargs
    public final IfFunctionReturn<K, T> addReturnAll(FunctionReturn<T> functionReturn, K... key) {
        for (K element : key) {
            if (ObjectUtil.isNotEmpty(element)) {
                this.mapReturn.put(element, functionReturn);
            }
        }
        return this;
    }

    /**
     * 确定key是否存在,如果存在,则执行value中的函数。
     * <p>
     * 函数有返回值
     * <p>
     * 若key为对象类型 则需重写 equal方法和hashcode方法
     * key值和map中的key值必须一致
     *
     * @param key the key need to verify
     */

    public IfFunctionReturn<K, T> doIfEqualReturn(@NotNull K key) {
        if (this.mapReturn.containsKey(key)) {
            this.result = mapReturn.get(key).invokeReturn();
            return this;
        }
        return this;
    }

    /**
     * 确定key是否存在,如果存在,则执行value中的函数。若不存在执行默认函数
     * <p>
     * 函数无返回值 增加默认执行函数 若传入条件皆不符合 则执行默认函数
     * <p>
     * 若key为对象类型 则需重写 equal方法和hashcode方法
     * key值和map中的key值必须一致
     *
     * @param key the key need to verify 条件值
     */
    public IfFunctionReturn<K, T> doIfEqualReturn(@NotNull K key, @NotNull FunctionReturn<T> defaultFunction) {
        boolean doesItContain = this.mapReturn.containsKey(key);
        if (doesItContain) {
            this.result = mapReturn.get(key).invokeReturn();
            return this;
        }
        this.result = defaultFunction.invokeReturn();
        return this;
    }

    /**
     * 比较对象类型是否一致 若一致则执行函数
     * <p>
     * 注意:此方法仅支持 同一个classloader加载两个类使用
     * <p>
     * 函数无返回值
     *
     * @param key the key need to verify 条件值
     */
    public IfFunctionReturn<K, T> doIfInstance(@NotNull K key) {
        mapReturn.forEach((setKey, value) -> {
            if (setKey.equals(key.getClass())) {
                this.result = value.invokeReturn();
            }
        });
        return this;
    }

    /**
     * 比较对象类型是否一致 若一致则执行函数 若不一致 执行默认函数
     * <p>
     * 注意:此方法仅支持 同一个classloader加载两个类使用
     * <p>
     * 函数无返回值 增加默认执行函数 若传入条件皆不符合 则执行默认函数
     *
     * @param key the key need to verify 条件值
     */
    public IfFunctionReturn<K, T> doIfInstance(@NotNull K key, @NotNull FunctionReturn<T> defaultFunction) {

        boolean execution = true;
        for (Map.Entry<K, FunctionReturn<T>> entry : mapReturn.entrySet()) {
            if (entry.getKey().equals(key.getClass())) {
                this.result = entry.getValue().invokeReturn();
                execution = false;
            }
        }
        if (execution) {
            this.result = defaultFunction.invokeReturn();
        }
        return this;
    }

    /**
     * 获取当前函数 返回值
     * <p>
     * 警告: 返回值可能为 null
     *
     * @return 返回对象
     */
    public T get() {
        if (result == null) {
            throw new NoSuchElementException("返回值对象为空!");
        }
        return result;
    }

    public T defaultValue(T other) {
        return result != null ? result : other;
    }
    /**
     * 执行完毕之后自动刷新 map 防止出现数据冲突
     */
    public IfFunctionReturn<K, T> refresh() {
        this.mapReturn.clear();
        return this;
    }

    /**
     * 创建桥接实例
     *
     * @param <K>条件类型泛型
     * @param <T>返回值类型泛型
     */
    public static <K, T> ResIfFunctionReturn<K, T> builder() {
        return new ResIfFunctionReturn<>();
    }

    public static class ResIfFunctionReturn<K, T> {
        private Map<K, FunctionReturn<T>> mapReturn;

        private ResIfFunctionReturn() {
        }

        public ResIfFunctionReturn<K, T> buildReturnIf(Map<K, FunctionReturn<T>> mapReturn) {
            this.mapReturn = mapReturn;
            return this;
        }

        public IfFunctionReturn<K, T> build() {
            IfFunctionReturn<K, T> functionReturn = new IfFunctionReturn<>();
            functionReturn.setMap(mapReturn);
            return functionReturn;
        }
    }
}

FunctionReturn函数接口

用于执行业务逻辑的接口封装


/**
 * @Author: yangjiahui
 * @Description: TODO 有返回值执行函数
 * @Date: 2020/12/22 4:20 下午
 */
@FunctionalInterface
public interface FunctionReturn<T> {
    /**
     * 有返回值的函数
     * @return
     */
    T invokeReturn();
}

其实这个if函数封装很简单,不过多的赘述。


三、复盘

接下来我们看下优化前的代码 和优化后的;

优化前:11个if判断逻辑(代码进行了业务删减)

public Object convert(Object destination, Object source, Class<?> destinationClass, Class<?> sourceClass) {
        if (ObjectUtil.isEmpty(source)) {}
        if (ObjectUtil.isNotEmpty(source) && source instanceof List) {
            if (optional.isPresent()) {
                if (object instanceof CouponDetail) {
                    if (ObjectUtil.isNotEmpty(couponDetails)) {
                            if (ObjectUtil.isEmpty(couponDetail)) {}
                            if (ObjectUtil.isNotEmpty(couponDetail){}
                        }
                        return String.valueOf(platformDiscount);
                    }
                }
                if (object instanceof com...enGet.CouponDetail) {
                    if (ObjectUtil.isNotEmpty(couponDetails)) {
                            if (ObjectUtil.isEmpty(couponDetail)) {}
                            if (ObjectUtil.isNotEmpty(couponDetail)
                        }
                        return String.valueOf(platformDiscount);
                    }
                }
            }
            return String.valueOf(platformDiscount);
        }
        return String.valueOf(platformDiscount);
    }

优化后:

Optional.ofNullable(source)
         .filter(fSource -> fSource instanceof List)
         .map(mSource -> {
             List<?> objectList = (List<?>) source;
			return objectList
                    .stream()
                    .findFirst()
                    .map(firstSource -> 
                    	FunctionBuilder
                                    .returnIf(new HashMap<Object, FunctionReturn<String>>())
                                    .addReturn(CouponDetail.class, () -> ifSearchCouponDetail(source))
                                    .addReturn(com...enGet.CouponDetail.class, () -> ifEnGetCouPonDetail(source))
                                    .doIfInstance(firstSource)
                                    .defaultValue(null)
                    ).orElse(null);
         })
         .orElse(String.valueOf(platformDiscount));

优点不用多讲…一幕了然呀!!!

敲代码容易,思想不易,转载请标注出处,谢谢诸神…

***江山父老能容我,不使人间造孽钱.***

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Using: Intel (R) PRO Network Connections SDK v2.30.10 EEUPDATE v5.30.10.00 Copyright (C) 1995 - 2017 Intel Corporation Intel (R) Confidential and not for general distribution. ----------------------------------------------------- Options: /HELP or /? Displays command line help. /EXITCODES Displays exit code help. /ALL Selects all adapters found in the system. /NIC=XX Selects a specific adapter (1-32). /BUS=XX Selects PCI bus of adapter to program. Must be used with the DEV parameter to specify an adapter. /DEV=XX Selects PCI device of the adapter to program. Must be used with the BUS parameter to specify an adapter. /FUN=XX Selects PCI function of the adapter to program. Must be used with both the BUS and DEV parameters to specify an adapter. Press to continue... /DEVICE= 4 hex digit device id of card to program. /SUBDEVICE= 4 hex digit subsystem device id of card to program. /DUMP Dumps EEPROM/Shadow RAM memory contents to file *.eep and flash memory to *.bin (if available) /MAC_DUMP_FILE Dumps the MAC address to a file usable by the /A command. /MAC_DUMP Displays the adapter LAN MAC address. /MAC_DUMP_ALL Displays all the MAC addresses. /MAC_ALL_TO_FILE Dumps all the MAC addresses to a file usable by the /MAC_ALL_FROM_FILE command. /MAC_ALL_FROM_FILE Programs all MAC addresses from text file to a device. File should contain 13 MAC addresses (9 for PEPs and 4 custom MAC addresses), one each line. EUI48 and EUI64 formats accepted. /CB Clears bits in the EEPROM, specified in . /SB Sets bits in the EEPROM, specified in . Press to continue... /RW Reads from the EEPROM. /WW Writes into in EEPROM. /MAC=macaddr [/NUM=PF_num] Programs the EEPROM/NVM with only the MAC address of macaddr without changing the rest of the EEPROM/NVM. /NUM is optional and I40E specific - it defines target PF. /A or /address Programs the EEPROM/NVM with only the MAC address from the without changing the rest of the EEPROM. /D or /DATA Programs the NVM [EEPROM/FLASH] with the contents of without changing the MAC address. /PHYNVM Programs the PHY NVM with the contents of /DEBUG Forces debug update to be used where applicable. Must be used with /D or /DATA switch. /CALCCHKSUM Forces the EEPROM checksum and CRCs to be updated. Press to continue... /EEPROMVER Displays the version of the EEPROM image. /INVMVERSION Displays the version of the iNVM image. /PCIINFO Displays the PCI information of the adapter. /ADAPTERINFO Displays additional information about the adapter, such as EtrackID, PF MAC address, or image and firmware version. /TEST Checks the EEPROM/NVM checksum(s) and size. /IDFLASH Displays the flash ID and its protected status. /VERSION Displays version and the diagnostic library information. /PHYID Programs the PHY ID NVM with the contents of . /PHYID_DUMP Dumps PHY ID NVM contents to a file with the name: _.bin /PHYID_VERIFY Verifies the PHY ID NVM image in eeprom against the file specified in . Press to continue... /FLASH_DUMP Dumps contents of the whole flash memory of selected adapters to *.bin file /EEPROM_DUMP Dumps contents of the EEPROM/Shadow RAM memory of selected adapters to *.eep file /GUI Brings up GUI mode. /GUI /HELP Displays GUI help. /NOPROT When programming an image for devices that support NVM protection, prevents protection from being enabled. This switch must be used with the /DATA command and has no effect on NVM devices that are already protected. /DEBUGLOG Log debug messages into the debugfile. /VERIFY Verifies the eeprom/NVM image in eeprom/NVM to the target file specified in . Press to continue... /CHECKIMAGE Verifies that the NVM in can be loaded over the running NVM. /VERIFYPHYNVM Verifies the PHY NVM image in eeprom to the target file specified in . /ADAPTERRESET Reset the adapter. *CAUTION* This will unload the driver for this device if present. /SANMAC_DUMP [/NUM=PF_num] Displays the dedicated MAC address for the SAN. /NUM is optional and i40e specific - it defines target PF. /SANMAC=macaddr [/NUM=PF_num] Programs the dedicated SAN MAC address withoutchanging the rest of the EEPROM. /NUM is optional and i40e specific - it defines target PF. /SANADDRESS Programs the dedicated SAN MAC address with the MAC address from . /INVMVERIFY /FILE=] Compares autoload configuration stored in OTP memory with the configuration defined in configuration file. /INVMTEST /FILE=] Report number of free space left in INVM if autoload configuration defined in configuration file would be applied. Press to continue... /INVMUPDATE /FILE=] Write new autoload configuration defined in Raw (*.raw) configuration file to empty INVM or updates current autoload configuration stored in INVM based on 'human readable' configuration file. /INVMISLOCKED Checks if autoload configuration stored in OTP memory is protected against write attempts. /INVMLOCK Sets unique record in autoload configuration stored in INVM protecting its content against further updates. /INVMGET Dumps autoload configuration stored in INVM to file with predefined name .otp. /FORCE Omits any warnings and forces command execution. /KEEPCONFIG This option lets you keep config words while upgrading eeprom. /PORT_MAC=macaddr /NUM=Port_num Programs the dedicated Port MAC address without changing the rest of the EEPROM. /PORT_MAC_DUMP /NUM=Port_num Display the adapter port MAC address. Press to continue... /CUSTOM_MAC mac_number mac_addr Programs the given custom mac address number [0-3] without changing the rest of the NVM (EUI48 and EUI64 formats supported). /SERIAL_MAC=macaddr Programs the dedicated PCIe serial MAC address without changing the rest of the EEPROM. /SERIAL_MAC_DUMP Display the adapter PCIe serial MAC address. /PF_MAC=macaddr /NUM=PF_num Programs the dedicated MAC address of a specified Physical Function This allows altering the mac addresses of inactive functions of a visible NIC. /PF_MAC_DUMP /NUM=PF_num Display MAC address of a selected Physical Function of the specified NIC. This allows dumping MAC addresses of inactive functions of a visible device. /MNG_MAC=macaddr /NUM=MNG_num Programs the dedicated MAC address of a specified Manageability Function This allows altering the mac addresses of inactive functions of a visible NIC. /MNG_MAC_DUMP /NUM=MNG_num Display MAC address of a selected Manageability Function of the specified NIC. This allows dumping MAC addresses of inactive functions of a visible device. /RO Programs RO words in EEPROM/SR with values taken from RO Module binary file.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼彻|Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值