如何高逼格的写java代码

2023-11-16

记录一些了解的高逼格、好用的java代码

欢迎大家补充,共同学习

1. 函数式接口—@FunctionalInterface

好处:高逼格、代码收拢、解藕、统一处理
适用范围:具有共性的接口调用代码
举个栗子:

在我们平时的微服务开发中,调用其他服务的接口,通常要把接口调用部分做异常处理(try catch),或者打印异常日志或者结果日志,并且也有可能做一些统一的调用处理,比如微服务接口熔断等处理,这个时候可以适用函数式接口收拢所有的微服务调用集中处理

这是一个微服务接口

public interface TestServer {
	T test();

	void test2();
}

普通的方式调用上面的微服务方法

public class RpcTestServerImpl{
	//引用微服务接口
	private TestServer testServer;	

	public T test(){
		try{
			return testServer.test();
		}catch (Exception e){
            log.error("RPC error: ", e);
        }
        return null;
	}
	
	public void test2(){
		try{
			testServer.test2();
		}catch (Exception e){
            log.error("RPC error: ", e);
        }
	}
}

使用函数式接口后的写法:先定义统一调用类

//首先定义一个ServerExecutor
public class ServerExecutor {
	//不需要返回值的
	public static void execute(Runnable runnable) {
        try {
            //调用前和调用后可以做一些处理,比如熔断、日志等等
            runnable.run();
            //调用前和调用后可以做一些处理,比如熔断、日志等等
        } catch (Exception e) {
            log.error("RPC error: ", e);
        }
    }

	//需要返回值的
	public static <T> T executeAndReturn(Callable<T> callable) {
        try {
        	//调用前和调用后可以做一些处理,比如熔断、日志等等
            return callable.call();
        } catch (Exception e) {
            log.error("RPC invoke error", e);
        }
        return null;
    }
}

使用统一定义的接口调用之后:

public class RpcTestServerImpl{
	//引用微服务接口
	private TestServer testServer;	

	public T test(){
        return ServerExecutor.executeAndReturn(() -> testServer.test());
	}

	public T test2(){
		ServerExecutor.execute(() -> testServer.test2());
	}
}

扩展知识:

@FunctionalInterface
官方文档:https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html
通过文档可以知道:
1、该注解只能标记在有且仅有一个抽象方法的接口上。
2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。
3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
4、该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。

2. List分页工具类

平时开发中可能会遇到一批数据的批量查询,但是接口限制每次只能查10个,多了查询失败,这个时候就很烦,还的手动给这一批数据分页再去掉接口查询,这个时候就可以用到com.google.common.collect.Lists工具的com.google.common.collect.Lists#partition方法,这个方法可以帮我们自动拆分List,根据我们传入的分批大小,把大集合拆成多个小集合
好处:方便实用,不用手写
举个栗子:

List<Long> userIdList = new ArrayList<>();
userIdList.add(1L);
userIdList.add(2L);
userIdList.add(3L);
userIdList.add(4L);
userIdList.add(5L);
userIdList.add(6L);
userIdList.add(7L);
userIdList.add(8L);
List<List<Long>> partition = Lists.partition(userIdList, 3);

上面这个代码,就可以把8个元素的userIdList通过Lists.partition拆分成3个元素一个的小集合,而且顺序不变,以前不知道这个方法,被同事diss一波,然后记录一下

3. 分割符的字符串和集合互转

日常开发经常遇到这种:1,2,3,4,5,6这种逗号分割的,要把他转成List,或者把一个List转成根据逗号分割的字符串,自己写的话就只能split加循环,这个时候又可以用到谷歌工具包
好处:方便实用,不用手写
举个栗子:

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.util.List;

public class CollectionUtil {

    /**
     * 把list的数据根据split拼接起来,自动过滤data中的null
     * 栗子:data:[1,3,4,6]  split:"."  return: "1.3.4.6"
     */
    public static String jointList(List data, String split){
        return Joiner.on(split).skipNulls().join(data);
    }

    /**
     * 把根据split分隔的字符串str变成List
     * 栗子:str:"1.3.5.7.9" split:"."   return:["1","3","5","7","9"]
     */
    public static List<String> splitIntoList(String str, String split){
        return Splitter.on(split).omitEmptyStrings().splitToList(str);
    }
}

4. 使用策略模式消除大篇幅if else

日常开发经常会遇到需要大量的if else判断,然后执行对应的代码,如果业务复杂,可能会十几个或者几十个if else,对于代码的扩展性和可读性有很大影响,而且看起来就很low,所以我们可以用到策略模式来消除大量的if else,并且让代码更具有健壮性
好处:高逼格,代码健壮,扩展性强
举个栗子:

//举例老的if else
if ("xxx".equals(type)) {
    System.out.println("do xxx");
} else if ("yyy".equals(type)) {
    System.out.println("do yyy");
} else if ("zzz".equals(type)) {
    System.out.println("do zzz");
} else if ("xyz".equals(type)) {
    System.out.println("do xyz");
}
// 后面可能会有更多

随着业务发展,可能会有非常多的if else,每次添加逻辑都要改这里的if else,代码篇幅会非常长,而且不利于维护,还违反了开闭原则
这个时候我们可以用策略模式出来处理:

//定义策略执行接口
public interface DataProcessor {

    Result handleData(Data data);

}

//定义每种数据的处理实现类
@Service("XxxProcessor")
public class XxxProcessor implements DataProcessor {
	@Override
	public Result handleData(Data data){
		//do xxx ....
		return null;
	}
}
@Service("YyyProcessor")
public class YyyProcessor implements DataProcessor {
	@Override
	public Result handleData(Data data){
		//do yyy ....
		return null;
	}
}
@Service("ZzzProcessor")
public class ZzzProcessor implements DataProcessor {
	@Override
	public Result handleData(Data data){
		//do zzz ....
		return null;
	}
}
@Service("XyzProcessor")
public class XyzProcessor implements DataProcessor {
	@Override
	public Result handleData(Data data){
		//do Xyz ....
		return null;
	}
}

每一个DataProcessor的实现类,就相当于一个if else中的处理逻辑执行器
然后定义一个枚举,把这些逻辑执行器管理起来:

public enum DataProcessorEnum {
	XXX(1, "xxx业务描述", "XxxProcessor"),
	YYY(2, "yyy业务描述", "YyyProcessor"),
	ZZZ(3, "zzz业务描述", "ZzzProcessor"),
	XYZ(4, "xyz业务描述", "XyzProcessor");
	/**
     * 业务type
     */
    private Integer type;

    /**
     * 业务描述
     */
    private String name;

    /**
     * 对应处理器
     * {@link DataProcessor}
     */
    private String processor;
    
	public static DataProcessorEnum valueOf(Integer type) {
        if (type == null) {
            return null;
        }
        for (DataProcessorEnum dataProcessorEnum : DataProcessorEnum.values()) {
            if (type.equals(dataProcessorEnum.getType())) {
                return dataProcessorEnum;
            }
        }
        return null;
    }
	
	//省略get等方法
}

当实际使用的时候,我们需要拿到对应处理器的实例,这里举例是在spring容器中为例,因为DataProcessor实现上都有@Service注解,如果不在spring容器中,可以自己实现反射获取实例的方法,这里就不再写反射获取了,大多数情况我们都是在spring环境中适用的,所以需要工具从spring 中获取对应实例,提供一个spring实例获取工具,这个应该很常见:


import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }

}

准备工作到这里应该算是完成了,实际使用中,可以这样操作:

public void dealData(Data bizData){
	if(bizData == null){
		return;
	}
	DataProcessorEnum dataProcessorEnum = DataProcessorEnum.valueOf(bizData.getType());
	if(dataProcessorEnum == null){
		//没有在枚举中匹配到处理器,说明业务参数不合法或者没有添加对应的业务枚举
		return;
	}
	DataProcessor processor = SpringUtil.getBean(dataProcessorEnum.getProcessor(), DataProcessor.class);
	if(processor == null){
		//没有从spring容器中获取到对应处理器到实例,属于异常情况,检查枚举配置和处理器是否正确注入spring容器
		return;
	}
	//交给对应到处理器去处理
	Result result = processor.handleData(bizData);
	//处理完成
}

到这里,使用策略模式消除if else就基本写完了,这里只是写出了基本到策略模式使用,还有其他更多的用法可以自己学习一下,而且其实我们使用策略模式前和使用后,感觉代码篇幅不减反增,肯定会想,这改造越改越复杂了呀
所以得出结论:if-else或switch case 这种分支判断的方式对于分支逻辑不多的简单业务,还是直观高效的。对于业务复杂,分支逻辑多,采用适当的模式技巧,会让代码更加清晰,容易维护,但同时类或方法数量也是倍增的。我们需要对业务做好充分分析,避免一上来就设计模式,避免过度设计!
另外再说一下,你就天天光写if else 和实习生有啥区别?怎么提升逼格?对吧

5. 当策略模式使用不值得的时候,如果优雅的处理大量if else

上面刚说完使用策略模式消除if else,立马先打脸自己,打脸自己才能成长,这次说一个使用java.util.function.Function jdk1.8 函数接口方式处理大篇幅if else的方式
好处:高逼格、比策略模式看起来简单明了(但是需要了解函数式编程,很简单)

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class Test {

    /**
     * 传统的 if else 解决方法
     * 当每个业务逻辑有 3 4 行时,用传统的策略模式不值得,直接的if else又显得不易读
     */
    public String doBizService(String order) {
        if ("type1".equals(order)) {
            return "执行业务逻辑1";
        } else if ("type2".equals(order)) {
            return "执行业务逻辑2";
        }else if ("type3".equals(order)) {
            return "执行业务逻辑3";
        }else if ("type4".equals(order)) {
            return "执行业务逻辑4";
        }else if ("type5".equals(order)) {
            return "执行业务逻辑5";
        }else if ("type6".equals(order)) {
            return "执行业务逻辑6";
        }else if ("type7".equals(order)) {
            return "执行业务逻辑7";
        }else if ("type8".equals(order)) {
            return "执行业务逻辑8";
        }else if ("type9".equals(order)) {
            return "执行业务逻辑9";
        }
        return "不在处理的逻辑中返回业务错误";
    }

	//---------------------------高逼格分割线------------------------------------

    /**
     * 业务逻辑分派Map
     * Function为函数式接口,
     * 下面代码中 Function<String, Object> 的含义是接收一个String类型的变量用来获取你要执行哪个Function,实际使用中可自行定义
     * Function执行完成返回一个Object类型的结果,这个结果就是统一的业务处理返回结果,实际使用中可自行定义
     */
    private static Map<String, Function<String, Object>> checkResultDispatcher = new HashMap<>();

    /**
     * 初始化 业务逻辑分派Map 其中value 存放的是 lambda表达式
     * 也可以依赖于spring的@PostConstruct 初始化checkResultDispatcher 根据各个技术栈调整
     */
    static  {
        checkResultDispatcher.put("type1", order -> testService.handleTyep1(order));
        checkResultDispatcher.put("type2", order -> testService.handleTyep2(order));
        checkResultDispatcher.put("type3", order -> testService.handleTyep3(order));
        checkResultDispatcher.put("type4", order -> testService.handleTyep4(order));
        checkResultDispatcher.put("type5", order -> testService.handleTyep5(order));
        checkResultDispatcher.put("type6", order -> testService.handleTyep6(order));
        checkResultDispatcher.put("type7", order -> testService.handleTyep7(order));
        checkResultDispatcher.put("type8", order -> testService.handleTyep8(order));
        checkResultDispatcher.put("type9", order -> testService.handleTyep9(order));
    }

    public Object handleBizService(String type) {
        //从逻辑分派Dispatcher中获得业务逻辑代码,result变量是一段lambda表达式
        Function<String, Object> result = checkResultDispatcher.get(type);
        if (result != null) {
            //执行这段表达式获得String类型的结果
            return result.apply(type);
        }
        return "不在处理的逻辑中返回业务错误";
    }
}

补一下关于java.util.function包下面各个类的简单了解

name type description
Consumer Consumer< T > 接收T对象,不返回值
Predicate Predicate< T > 接收T对象并返回boolean
Function Function< T, R > 接收T对象,返回R对象
Supplier Supplier< T > 提供T对象(例如工厂),不接收值
UnaryOperator UnaryOperator< T > 接收T对象,返回T对象
BiConsumer BiConsumer<T, U> 接收T对象和U对象,不返回值
BiPredicate BiPredicate<T, U> 接收T对象和U对象,返回boolean
BiFunction BiFunction<T, U, R> 接收T对象和U对象,返回R对象
BinaryOperator BinaryOperator< T > 接收两个T对象,返回T对象

6. 通用的redis获取值并处理空缓存方法

日常开发会遇到一种缓存无效的情况:普通用获取redis值的时候,发现获取到的是空字符串,这个时候就会去查库,然后mysql库里面查询结果也是空的,这个时候就会有问题,如果一直调用这个key获取数据,缓存查不到,数据库也查不到,如果高频调用就会对数据库造成压力。对于这种情况,可以在库里查询为空的时候,给redis里面存一个空缓存{},当下次查询redis的时候,得到的不再是空字符串"",对于这种逻辑,本来是需要自己写逻辑的,然后每个这种都要写一遍判断逻辑,后来在开发中遇到同事(大佬)写的一个通用方法,很好用,记录下来:

public class CacheConstant {
   /**
    * 各类空缓存对象value
    */
   public static final String EMPTY_CACHE = "{}";

}


public static <T> T get(String key, Long timeout, Class<T> clazz, Callable<T> getFunction, Runnable exceptionRunnable) {
    RedisService redisService = SpringUtil.getBean(RedisService.class);
    if (redisService == null) {
        log.error("Redis查询接口 初始化异常");
        return null;
    }
    if (StringUtils.isBlank(key)) {
        return null;
    }
    String cacheValue = redisService.get(key);
    T object = null;
    if (StringUtils.isNotBlank(cacheValue)) {
        if (CacheConstant.EMPTY_CACHE.equals(cacheValue)) {
            return null;
        }

        try {
            object = JSONObject.parseObject(cacheValue, clazz);
        } catch (Exception e) {
            log.error("RedisUtil get error, key:[" + key + "], cacheValue:[" + cacheValue + "]", e);
        }

        if (object != null) {
            return object;
        } else {
            //说明解析发生了异常,调用解析异常处理,比如可以做一些缓存过期处理之类的操作
            if(exceptionRunnable != null){
                exceptionRunnable.run();
            }
        }
    }

    try {
        if(getFunction != null){
            object = getFunction.call();
        }
    } catch (Exception e) {
        log.error("getFunction.call error", e);
        return null;
    }

    cacheValue = object != null ? JsonUtil.object2json(object) : CacheConstant.EMPTY_CACHE;
    redisService.set(key, cacheValue, timeout);
    return object;
}

7. CompletableFuture基本使用

//创建第一个任务CompletableFuture  使用线程池taskExecutor
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> countVO.setTotal(baseDao.selectCount(queryWrapper)), taskExecutor);

//创建第二个任务CompletableFuture  使用线程池taskExecutor
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> countVO.setTotal(baseDao.selectCount(queryWrapper)), taskExecutor);

//创建第三个任务CompletableFuture  使用线程池taskExecutor
CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> countVO.setTotal(baseDao.selectCount(queryWrapper)), taskExecutor);

//添加三个CompletableFuture到allFuture 
CompletableFuture<Void> allFuture = CompletableFuture.allOf(future1, future2, future3);
// allFuture 等待三个任务执行完成并结束,超时时间200毫秒
allFuture.get(200, TimeUnit.MILLISECONDS);

该用法类似于CountDownLatch的使用,创建多个异步任务,在主线程中等待每个任务执行完成
CompletableFuture的方法有很多,各种组合可以实现不同的功能。大致通过方法名称可以总结为:

创建类

  • runAsync 异步执行,无返回值
  • supplyAsync 异步执行,有返回值
  • anyOf 任意一个执行完成,就可以进行下一步动作
  • allOf 全部完成所有任务,才可以进行下一步任务

接续类

  • 以Async结尾的方法,都是异步方法,对应的没有Async则是同步方法,一般都是一个异步方法对应一个同步方法。
  • 以Async后缀结尾的方法,都有两个重载的方法,一个是使用内容的forkjoin线程池,一种是使用自定义线程池
  • 以run开头的方法,其入口参数一定是无参的,并且没有返回值,类似于执行Runnable方法。
  • 以supply开头的方法,入口也是没有参数的,但是有返回值
  • 以Accept开头或者结尾的方法,入口参数是有参数,但是没有返回值
  • 以Apply开头或者结尾的方法,入口有参数,有返回值
  • 带有either后缀的方法,表示谁先完成就消费谁
  • whenCompleteAsync:处理完成或异常,无返回值
  • handleAsync:处理完成或异常,有返回值

状态取值类

  • join 合并结果,等待
  • get 合并等待结果,可以增加超时时间;get和join区别,join只会抛出unchecked异常,get会返回具体的异常

8. @ConditionalOnMissingBean使用

@ConditionalOnMissingBea该注解表示,如果存在它修饰的类的bean,则不需要再创建这个bean。日常代码中写公共jar包代码,经常会有接口需要默认实现和自定义实现,jar包中写公共实现,如果需要对接口实现自定义实现,就可以使用@ConditionalOnMissingBean快速实现

/**
 * 默认实现配置
 */
@Configuration
public class DefaultConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "TestDefaultService")//指定Bean的名称
    public TestDefaultService testService() {
        return (param) -> {
        	//...默认公共实现
        };
    }
}
@Qualifier("TestDefaultService")//指定Bean名称
@Resource
private TestDefaultService testDefaultService;

这样使用之后,当手动实现了TestDefaultService 并指定BeanName为“TestDefaultService”,比如在接口实现类上这样写之后

@Service("TestDefaultService")

手动实现的接口就会被注入,而默认实现的就不会被注入,如果不手动实现接口,那么默认实现就会被注入。

9. 使用函数式编程实现代理模式

先上代码:

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 返回值
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Test1DTO extends TestBaseDTO {

    private String name;

}

import lombok.Data;

/**
 * 返回值基类
 */
@Data
public class TestBaseDTO {

    private Integer value;

}
public interface Test1Service {

    TestBaseDTO handle() throws Exception;

}
public class Test1Util {

    public static <R extends TestBaseDTO> R execute(Test1Service test1Service) throws Exception {
        System.out.println("在执行之前做一些事情");
        R handle = (R) test1Service.handle();
        System.out.println("在执行之后做一些事情");
        return handle;
    }

}
/**
 * 测试类
 */
public class Test1 {

    public static void main(String[] args) throws Exception {

        TestBaseDTO execute = Test1Util.execute(() -> {
            // 这里可以写想要执行的逻辑代码
            // 返回值可以自定义  只要继承TestBaseDTO就行
            Test1DTO testBaseDTO = new Test1DTO();
            testBaseDTO.setValue(1);
            testBaseDTO.setName("test");
            return testBaseDTO;
        });

        System.out.println(execute);

    }

}

如上代码,就是通过函数式编程搞了一个Test1Util 来处理逻辑代码执行时被代理的逻辑。这个方式可改造的方式很多,可以轻易改造成适合自己的业务的写法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何高逼格的写java代码 的相关文章

随机推荐

  • 在外包公司熬了 3 年终于进了字节,竭尽全力....

    其实两年前校招的时候就往字节投了一次简历 结果很明显凉了 随后这个理想就被暂时放下了 但是这个种子一直埋在心里这两年除了工作以外 也会坚持写博客 也因此结识了很多优秀的小伙伴 从他们身上学到了特别多东西 把这次面试分享出来 也是希望可以帮助
  • C语言:函数指针和指针函数学习

    一 指针函数 定义 指针函数就是返回值类型是指针的函数 后面说的是本身是什么 前面说的是返回值类型是什么 声明方法 类型标识符 函数名 参数列表 int fun int x int y int fun int x int y int fun
  • 使用C++来创建界面

    上节讲到 Qt 支持两种创建界面的方式 一种是使用C 代码 Qt 自诞生以来就支持 另一种是使用 QML 可以创建个性化的界面 Qt 提供了多种工程类型 选择不同的工程类型将导致使用不同的方式来创建界面 本节先讲解C 的使用 首次打开Qt
  • netty 无阻塞队列 MpscArrayQueue,一个字就是快

    netty提供了高效的线程安全的队列 MpscArrayQueue 一个字快 至于快的原因可以去查看相关的文章 内存的伪共享先关的内容 import static java lang Thread sleep import io netty
  • nutz ajax ie8,Nutz.Json 在Mvc中的用法

    Mvc中使用Json 第一种 输出用 Ok json locked password salt 第二种 输入用的 AdaptBy type JsonAdaptor class Ok中的json 首先 必须再再再强调一次 如果返回值是Stri
  • 网络协议之以太网协议解析

    Ethernet 以太网协议 用于实现链路层的数据传输和地址封装 MAC 以太网是局域网使用最广泛的协议 由于部署简单 价格低廉 被IEEE委员会标准化 封装原理 以太网的数据帧格式如下图所示 它由6个字节的目的MAC地址 6个字节的源MA
  • Java八大基本数据类型

    Java中主要有八种基本数据类型 1 整型 byte short int long 2 字符型 char 3 浮点型 float double 4 布尔型 boolean 一 整型 Java中整型数据属于有符号数 即第一个bit位为0表示正
  • 2023 前端一场面试及答案整理

    金三马上就要开始了 俗话说得好 知己知彼百战百胜 多准备总是没有错的 以面试的形式和大家一起学习 一起回顾我们的职场生涯 今天简单总结一下我个人去面试 包括我在面试别人时的经验 加油加加油 目录 开头热场问题 1 说一下工作中解决过比较困难
  • 解决TortoiseGit每次Pull或者Push都需要输用户名密码的问题

    解决TortoiseGit每次Pull或者Push都需要输用户名密码的问题 每次提交代码到仓库都要输入用户名和密码 王同学差点哭了 忍住 忍住 不能哭 不能哭 解决方法如下 Right click TortoiseGit Settings
  • Linux 进程间通信之管道

    进程之间的通讯之管道 目录 1 无名管道 2 有名管道 3 管道读写规则 1 无名管道 管道是一种最基本的IPC机制 作用于父子进程之间 完成数据传递 管道有以下特性 1 其本质是一个伪文件 实为内核缓冲区 其本质是一个伪文件 实为内核缓冲
  • Vue 快速删除

    Vue 快速删除nodejs配置的快速删除node modules 删除文件夹及文件 cnpm i rimraf g 这个需要cmd管理员命令运行 删除文件及文件夹 rimraf f node modules
  • 微信小程序Markdonw、HTML富文本内容显示解决办法

    Towxml Towxml 是一个可将HTML markdown转换为WXML WeiXin Markup Language 的渲染库 由于微信小程序不能直接渲染HTML 因此富文本编辑器生成的HTML内容无法直接在小程序中展示 可能是出于
  • HTML网页入门之注释怎么写

    HTML网页入门之注释怎么写 为了增强网页的可读性注释是必不可少的 下面我们就来谈一谈 HTML网页的注释应该怎么写 HTML注释的作用 1 用注释的内容不会显示在浏览器中 注释标签用于在源代码中插入注释 注释的内容不会显示在浏览器中 对关
  • GoogLeNet网络详解与模型搭建

    文章目录 1 模型介绍 2 GoogLeNet详解 Inception模块 辅助分类器 3 GoogLeNet网络结构 4 Pytorch模型搭建代码 1 模型介绍 GoogLeNet是2014年Christian Szegedy等人在20
  • qmake source code 解读

    qmake 主要框架流程 qmake的主要功能执行入口在main cpp中的runQMake int argc char argv 中 其主要框架流程如下 runQMake int argc char argv QMakeVfs vfs 初
  • 2023Python该怎么学?我用这14张学习路线图,直观的告诉你

    我知道对于绝大多数的人来说 学习编程的第一目的其实就是想找一份有发展前景 并且薪资待遇还不错的工作 那么肯定是哪个编程语言的就业前景好 就越值得学习 Python作为当下最热的一门编程语言 刚好就符合这个条件 所以对于绝大部分人来说Pyth
  • java基于寄存器_基于栈的指令集与基于寄存器的指令集的区别,JVM指令集实例...

    现代JVM在执行Java代码的时候 通常都会将解释执行与编译执行两者结合起来 所谓解释执行 就是通过解释器来读取字节码 遇到相应的指令就去执行该指令 所谓编译执行 就是通过即时编译器 Just In Time JIT 将字节码转为本地机器码
  • 玩转ChatGPT:Custom instructions (vol. 1)

    一 写在前面 据说GPT 4又被削了 前几天让TA改代码 来来回回好几次才成功 可以看到之前3小时25条的限制 现在改成了3小时50条 可不可以理解为 以前一个指令能完成的任务 现在得两条指令 可能作为补偿 OpenAI对于Plus用户开放
  • 兼容和适配的区别

    兼容测试是app能否在不同品牌的手机上进行安装卸载等测试 适配测试是app能否在不同尺寸 不同分辨率的终端上能否正常显示的测试 转载于 https www cnblogs com bubutianshu p 11263395 html
  • 如何高逼格的写java代码

    记录一些了解的高逼格 好用的java代码 欢迎大家补充 共同学习 1 函数式接口 FunctionalInterface 好处 高逼格 代码收拢 解藕 统一处理 适用范围 具有共性的接口调用代码 举个栗子 在我们平时的微服务开发中 调用其他