本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法。

GA算法的逻辑还是贴下:

好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用方法。

pom依赖,毕竟java的嘛,就不要用matlab、R、python这些了

<!-- https://mvnrepository.com/artifact/io.jenetics/jenetics -->
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics.ext</artifactId>
<version>5.1.0</version>
</dependency>

先看看我们提供的这个框架,能怎样简化业务侧代码吧:

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5); //需要指定一个线程池,因为GA算法需要很多运算 Demo1SolutionConverter demo1SolutionConverter = new Demo1SolutionConverter(); //这个class中定义了GA算法所需的底层基因序列的定义、以及业务解决方案class与基因的互相转换逻辑
Demo1FitnessBuilder fitnessBuilder = new Demo1FitnessBuilder(); //这个class定义了适应度函数的指向(遗传算法非常依赖适应度函数,非常非常依赖,重中之重) EngineInvokeOptions options = new EngineInvokeOptions(); //引擎调用默认参数,如需改写默认参数单独修改即可
options.setFitnessBuilder(fitnessBuilder);
options.setEnableMaxLimits(true); //设置为停止条件为最大种群次数限制
options.setMaxLimits(20); //设置为最大次数限制为20次,既:20次种群迭代 for(int idx=0;idx<20;idx++) { //连续执行20次看效果
MinMaxScaler minMaxScaler = new MinMaxScaler(100, false); GAEngine gaEngine = new GAEngine(50, executorService); Demo1SolutionConverter.Demo1Solution solution = (Demo1SolutionConverter.Demo1Solution) gaEngine.generate(demo1SolutionConverter, minMaxScaler, options);
System.out.println(solution.toString());
} executorService.shutdown();
}  

我们先看看核心class:Demo1SolutionConverter,这个是每个业务都不同的地方,需要单独业务单独编码

public class Demo1SolutionConverter extends DefaultSolutionConverter {                                         //DefaultSolutionConverter是框架里的默认实现,已经实现了很多默认方法
@Override
public AbstractSolution convert2Solution(EvolvingSolutionInfo solutionInfo) {
Demo1Solution solution=new Demo1Solution();
solution.setFitnessValues(solutionInfo.getFitnessValues()); Genotype<IntegerGene> geneMap=solutionInfo.getMap(); //这个是获取基因架 Chromosome<IntegerGene> chromosome=geneMap.getChromosome(); //获取默认的也就是第一个基因条 for(int idx=0;idx<chromosome.length();idx++) //开始业务解码
{
IntegerGene integerGene=chromosome.getGene(idx);
if(integerGene.intValue()==1)
{
solution.getSelectedIds().add(idx); //这里实现的解码逻辑:共10个数字,有2种可能0和1,0代表不选中,1代表选中,选中了就会加入selectedIds这个List里
}
} return solution;
} @Override
public Genotype<IntegerGene> loadGenotype() { //这个是唯一一个DefaultSolutionConverter种的抽象方法,必须实现,用来定义基因序列的组成
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(10)) //10个基因,每个基因只有2种可能,0或者1
); return genotype;
} public double test(AbstractSolution solution) //这个是适应度函数定义,要注意入参和出参,这2个是固定的
{ //test是method名,待会会在后面介绍,会在其他class中指定过来
Demo1Solution s=(Demo1Solution)solution; long 偶数个数=s.getSelectedIds().stream().filter(f->f%2==0).count();
long 奇数个数=s.getSelectedIds().stream().filter(f->f%2!=0).count(); double score=(-偶数个数)+(+奇数个数); //score是适应度函数的分值,越小越优,由于我们希望不要奇数、只要偶数,所以偶数部分为负号、奇数部分为正号
return score;
} @Data
public class Demo1Solution extends DefaultSolution { //这个是业务解码后存放的class,很好理解 private List<Integer> selectedIds=new ArrayList<>(); @Override
public String toString() {
StringBuilder stringBuilder=new StringBuilder(); for(int id:selectedIds)
{
stringBuilder.append(id);
stringBuilder.append(", ");
} return stringBuilder.toString();
}
}
}  

然后再看看Demo1FitnessBuilder类,既:适应度函数指向类:

public class Demo1FitnessBuilder implements FitnessBuilder {
@Override
public Tuple2<Map<String, Object>, List<Tuple3<String, String, Double>>> build() { Map<String, Object> objConfigs= buildObjectAndConfigs();
List<Tuple3<String, String, Double>> fitnessConfigs=buildFitnessConfigs(); return Tuples.of(objConfigs, fitnessConfigs);
} private Map<String, Object> buildObjectAndConfigs() { Map<String, Object> configs=new HashMap<>(); Demo1SolutionConverter obj=new Demo1SolutionConverter(); //这里定义的是n个适应度函数所在的对象(此处只定义了1个,也可以多个)
configs.put("obj", obj); return configs;
} private List<Tuple3<String, String, Double>> buildFitnessConfigs() {
List<Tuple3<String, String, Double>> fitnessConfigs = new ArrayList<>(); fitnessConfigs.add(Tuples.of("obj", "test", 1D)); //obj和上面的对应,test指明了适应度函数是在obj这个对象中方法名为test的函数
//此处也可以多个
//1D代表默认权重,也可以定期较低的权重,比如:0.5D这种
   return fitnessConfigs;
}
}

  

看看程序的输出:

0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 3, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,

  

如同大家所见,GA算法的问题在于不太稳定,只能代表一种优化趋势,导致这样的原因有很多,最重要的原因还是在于智能算法一般使用的场景都是由于传统算法无能为力的场景,或者无法穷举的场景。

下面看看加大种群迭代次数是否能解决:

options.setMaxLimits(100);
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,

  

算是表面解决了,但其实还有很多因素能导致不稳定,比如,我们从当前的10个数字,enlarge到50个数字,会怎样:

@Override
public Genotype<IntegerGene> loadGenotype() {
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(50))
); return genotype;
}
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 41, 42, 44, 46,
0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
2, 4, 5, 6, 8, 10, 12, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 8, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 42, 44, 46, 48,
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 47, 48, 49,
0, 2, 4, 6, 8, 10, 12, 13, 14, 16, 18, 20, 22, 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
0, 2, 4, 6, 8, 10, 12, 13, 16, 18, 19, 22, 24, 26, 28, 30, 31, 32, 36, 38, 40, 42, 43, 44, 45, 46, 48,
0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 25, 26, 28, 30, 32, 34, 38, 40, 42, 44, 45, 46, 48,
0, 1, 2, 4, 5, 6, 8, 10, 11, 12, 14, 16, 18, 20, 21, 22, 23, 24, 26, 28, 30, 32, 36, 38, 40, 42, 44, 46, 48,
2, 4, 6, 8, 10, 12, 14, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 18, 20, 22, 24, 26, 28, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 38, 40, 42, 43, 44, 46, 48, 49,
0, 2, 4, 6, 8, 9, 10, 12, 14, 18, 22, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 13, 14, 16, 18, 20, 22, 24, 26, 28, 31, 32, 34, 38, 40, 42, 45, 46, 48,
0, 2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 27, 29, 30, 32, 34, 36, 38, 40, 46, 48,
0, 4, 6, 8, 10, 12, 14, 16, 20, 22, 24, 25, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,

  

哇塞,简直了,这结果。。。

再来:

options.setMaxLimits(2000);
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,   

  

体会到了不确定的痛苦了吗?

再来:

//        options.setEnableMaxLimits(true);
// options.setMaxLimits(2000);
options.setEnableSteadyFitness(true); //设置为稳定适应度函数值默认
options.setSteadyFitnessValue(1000); //当连续1000次的种群迭代的最优适应度函数值都稳定的时候,稳定就是分值没有超越当前的最好分值,然后才停止算法
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,

  

遗传算法是非常耗费算力的,能其他算法就尽量其他算法来做,真的。虽然GA也有很多优点,比如:

  1. 当无法穷举时,这个算法就是好的
  2. 当数据量较少时,这个算法也挺稳定(要调好参数)
  3. 当计算什么是好,什么是坏时的逻辑是非线性的时候,GA算法也是个很好的选项

完整代码下载,带demo+自研框架+底层是jenetics

完整下载 

 

遗传算法框架-基于java jenetics库实现的更多相关文章

  1. 自定义RPC框架--基于JAVA实现

    视频教程地址 DT课堂(原名颜群) 整体思路RPC(Remote Procedure Call),即远程过程调用.使用RPC,可以像使用本地的程序一样使用远程计算机上的程序.RPC使得开发分布式程序更 ...

  2. 完全开源Android网络框架 — 基于JAVA原生的HTTP框架

    HttpNet网络请求框架基于HttpUrlConnection,采用Client + Request + Call的请求模型,支持https默认证书,数字安全证书.支持http代理!后续将会实现队列 ...

  3. 【原创】三分钟教你学会MVC框架——基于java web开发(2)

    没想到我的上一篇博客有这么多人看,还有几位看完之后给我留言加油,不胜感激,备受鼓励,啥都别说了,继续系列文章之第二篇.(如果没看过我第一篇博客的朋友,可以到我的主页上先浏览完再看这篇文章,以免上下文对 ...

  4. 【原创】三分钟教你学会MVC框架——基于java web开发(1)

    MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用于组织代码用一种业务逻辑和数据显示分离的方法. ...

  5. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  6. 基于java spring框架开发部标1078视频监控平台精华文章索引

    部标1078视频监控平台,是一个庞杂的工程,涵盖了多层协议,部标jt808,jt809,jt1078,苏标Adas协议等,多个平台功能标准,部标796标准,部标1077标准和苏标主动安全标准,视频方面 ...

  7. 9个基于Java的搜索引擎框架

    在这个信息相当繁杂的互联网时代,我们已经学会了如何利用搜索引擎这个强大的利器来找寻目标信息,比如你会在Google上搜索情人节如何讨女朋友欢心,你也会在百度上寻找正规的整容医疗机构(尽管有很大一部分广 ...

  8. 基于Java Netty框架构建高性能的部标808协议的GPS服务器

    使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...

  9. 基于Java Mina框架的部标808服务器设计和开发

    在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...

随机推荐

  1. css选择器大全

    1.元素选择器 这是最基本的CSS选择器,HTML文档中的元素本身就是一个选择器: p {line-height:1.5em; margin-bottom:1em;} //设置p元素行高1.5em,距 ...

  2. selenium自动爬取网易易盾的验证码

    我们在爬虫过程中难免会遇到一些拦路虎,比如各种各样的验证码,时不时蹦出来,这时候我们需要去识别它来继续我们的工作,接下来我将爬取网一些滑动验证码,然后通过百度的EasyDL平台进行数据标注,创建模型, ...

  3. 最小割&网络流应用

    重要链接 基础部分链接 : 二分图 & 网络流初步 zzz大佬博客链接 : 网络流学习笔记 重点内容:最小割二元关系新解(lyd's ppt) 题目:网络流相关题目 lyd神犇课件链接 : 网 ...

  4. 题解 洛谷 P5303 【[GXOI/GZOI2019]逼死强迫症】

    可以先去考虑没有\(1 \times 1\)的砖块的情况,对于最后一个位置只有两种情况,一个是竖着用一块砖铺设\(2 \times 1\),另一个为横着用两块砖铺设\(2 \times 2\). 设没 ...

  5. MySQL组复制MGR(一)-- 技术概述

    (一)复制技术的发展 MySQL的复制技术主要经历了异步主从复制,半同步复制,组复制(Group Replication)3个阶段. (1)传统的异步主从复制 传统的MySQL提供了一种简单的主从复制 ...

  6. cli框架 获取 命令行 参数

    package main import ( "fmt" "log" "os" "github.com/urfave/cli&quo ...

  7. 《Python编程第4版 上》高清PDF|百度网盘免费下载|Python基础编程

    <Python编程第4版 上>高清PDF|百度网盘免费下载|Python基础编程 提取码:8qbi  当掌握Python的基础知识后,你要如何使用Python?Python编程(第四版)为 ...

  8. 容器centos7安装部署ansible

    容器centos7安装部署ansible centos镜像版本及ansible版本 centos:centos7.5.1804 ansible:2.9.11 启动容器并进入容器 docker run ...

  9. 第十二章 类加载器&反射

    12.1.类加载器 12.1.1.类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载.类的连接.类的初始化这三个步骤来对类进行初始化.如果不出现意外情况,JVM将会连续完成 ...

  10. django 命令行命令

    django-admin startproject 项目名 django-admin startproject python manage.py makemigrations python manag ...