how2j.cn

本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



4分55秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器



示例 1 : 创建自定义异常   
示例 2 : 抛出自定义异常   
示例 3 : 练习-自定义异常   
示例 4 : 答案-自定义异常   

示例 1 :

创建自定义异常

edit
一个英雄攻击另一个英雄的时候,如果发现另一个英雄已经挂了,就会抛出EnemyHeroIsDeadException
创建一个类EnemyHeroIsDeadException,并继承Exception
提供两个构造方法
1. 无参的构造方法
2. 带参的构造方法,并调用父类的对应的构造方法
class EnemyHeroIsDeadException extends Exception{ public EnemyHeroIsDeadException(){ } public EnemyHeroIsDeadException(String msg){ super(msg); } }
class EnemyHeroIsDeadException extends Exception{
    
	public EnemyHeroIsDeadException(){
		
	}
    public EnemyHeroIsDeadException(String msg){
        super(msg);
    }
}
示例 2 :

抛出自定义异常

edit
在Hero的attack方法中,当发现敌方英雄的血量为0的时候,抛出该异常
1. 创建一个EnemyHeroIsDeadException实例
2. 通过throw 抛出该异常
3. 当前方法通过 throws 抛出该异常

在外部调用attack方法的时候,就需要进行捕捉,并且捕捉的时候,可以通过e.getMessage() 获取当时出错的具体原因
抛出自定义异常
package charactor; public class Hero { public String name; protected float hp; public void attackHero(Hero h) throws EnemyHeroIsDeadException{ if(h.hp == 0){ throw new EnemyHeroIsDeadException(h.name + " 已经挂了,不需要施放技能" ); } } public String toString(){ return name; } class EnemyHeroIsDeadException extends Exception{ public EnemyHeroIsDeadException(){ } public EnemyHeroIsDeadException(String msg){ super(msg); } } public static void main(String[] args) { Hero garen = new Hero(); garen.name = "盖伦"; garen.hp = 616; Hero teemo = new Hero(); teemo.name = "提莫"; teemo.hp = 0; try { garen.attackHero(teemo); } catch (EnemyHeroIsDeadException e) { // TODO Auto-generated catch block System.out.println("异常的具体原因:"+e.getMessage()); e.printStackTrace(); } } }
示例 3 :

练习-自定义异常

edit  姿势不对,事倍功半! 点击查看做练习的正确姿势
MyStringBuffer的插入和删除方法中的边界条件判断,用抛出异常来解决
例: insert(int pos, String b) , 当pos 是负数的时候,抛出自定义异常
需要实现自定义两种异常
IndexIsNagetiveException 下标为负异常
IndexIsOutofRangeException 下标超出范围异常
以下是需要调用这些异常的场景:

pos<0

抛出 IndexIsNagetiveException

pos>length

抛出 IndexIsOutofRangeException


null==b

抛出 NullPointerException


start<0

抛出 IndexIsNagetiveException


start>length

抛出 IndexIsOutofRangeException


end<0

抛出 IndexIsNagetiveException


end>length

抛出 IndexIsOutofRangeException


start>=end

抛出 IndexIsOutofRangeException

注意: 接口IStringBuffer中声明的方法需要抛出异常
示例 4 :

答案-自定义异常

edit
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费4个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费4个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

4分51秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


package exception; public class IndexIsNagetiveException extends Exception{ }
package exception; public class IndexIsOutofRangeException extends Exception { }
package character; import exception.IndexIsNagetiveException; import exception.IndexIsOutofRangeException; public interface IStringBuffer { public void append(String str) throws IndexIsOutofRangeException, IndexIsNagetiveException; ; //追加字符串 public void append(char c) throws IndexIsOutofRangeException, IndexIsNagetiveException; ; //追加字符 public void insert(int pos,char b) throws IndexIsOutofRangeException, IndexIsNagetiveException; //指定位置插入字符 public void insert(int pos,String b) throws IndexIsOutofRangeException, IndexIsNagetiveException; ; //指定位置插入字符串 public void delete(int start) throws IndexIsOutofRangeException, IndexIsNagetiveException; ; //从开始位置删除剩下的 public void delete(int start,int end) throws IndexIsOutofRangeException, IndexIsNagetiveException; ; //从开始位置删除结束位置-1 public void reverse(); //反转 public int length(); //返回长度 }
package character; import exception.IndexIsNagetiveException; import exception.IndexIsOutofRangeException; public class MyStringBuffer implements IStringBuffer { int capacity = 16; int length = 0; char[] value; public MyStringBuffer() { value = new char[capacity]; } // 有参构造方法 public MyStringBuffer(String str) { this(); if (null == str) return; if (capacity < str.length()) { capacity = value.length * 2; value = new char[capacity]; } if (capacity >= str.length()) System.arraycopy(str.toCharArray(), 0, value, 0, str.length()); length = str.length(); } @Override public void append(String str) throws IndexIsNagetiveException, IndexIsOutofRangeException { insert(length, str); } @Override public void append(char c) throws IndexIsNagetiveException, IndexIsOutofRangeException { append(String.valueOf(c)); } @Override public void insert(int pos, char b) throws IndexIsNagetiveException, IndexIsOutofRangeException { insert(pos, String.valueOf(b)); } @Override public void delete(int start) throws IndexIsNagetiveException, IndexIsOutofRangeException { delete(start, length); } @Override public void delete(int start, int end) throws IndexIsNagetiveException, IndexIsOutofRangeException { // 边界条件判断 if (start < 0) throw new IndexIsNagetiveException(); if (start > length) throw new IndexIsOutofRangeException(); if (end < 0) throw new IndexIsNagetiveException(); if (end > length) throw new IndexIsOutofRangeException(); if (start >= end) throw new IndexIsOutofRangeException(); System.arraycopy(value, end, value, start, length - end); length -= end - start; } @Override public void reverse() { for (int i = 0; i < length / 2; i++) { char temp = value[i]; value[i] = value[length - i - 1]; value[length - i - 1] = temp; } } @Override public int length() { // TODO Auto-generated method stub return length; } @Override public void insert(int pos, String b) throws IndexIsNagetiveException, IndexIsOutofRangeException { // 边界条件判断 if (pos < 0) throw new IndexIsNagetiveException(); if (pos > length) throw new IndexIsOutofRangeException(); if (null == b) throw new NullPointerException(); // 扩容 if (length + b.length() > capacity) { capacity = (int) ((length + b.length()) * 2.5f); char[] newValue = new char[capacity]; System.arraycopy(value, 0, newValue, 0, length); value = newValue; } char[] cs = b.toCharArray(); // 先把已经存在的数据往后移 System.arraycopy(value, pos, value, pos + cs.length, length - pos); // 把要插入的数据插入到指定位置 System.arraycopy(cs, 0, value, pos, cs.length); length = length + cs.length; } public String toString() { char[] realValue = new char[length]; System.arraycopy(value, 0, realValue, 0, length); return new String(realValue); } public static void main(String[] args) { try { MyStringBuffer sb = new MyStringBuffer("there light"); System.out.println(sb); sb.insert(0, "let "); System.out.println(sb); sb.insert(10, "be "); System.out.println(sb); sb.insert(0, "God Say:"); System.out.println(sb); sb.append("!"); System.out.println(sb); sb.append('?'); System.out.println(sb); sb.reverse(); System.out.println(sb); sb.reverse(); System.out.println(sb); sb.delete(0, 4); System.out.println(sb); sb.delete(4); System.out.println(sb); } catch (IndexIsNagetiveException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IndexIsOutofRangeException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2024-07-05 改进后的MyStringBufferPro
虚心求学




新增数组越界、不规范的异常声明,统一使用 checkIndexValid的方法来检查索引是否合理。
package j2se;

public interface IStringBuffer {
	public void append(String str) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void append(char c);
	public void append(String...strs) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void insert(int pos,char b) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void insert(int pos,String b) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void delete(int start) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void delete(int start,int end) throws IndexIsNagetiveException, IndexIsOutofRangeException;
	public void reverse();
	public int length();
}

---------------------------下一个类-------------------------------------------------------

package j2se;


import java.util.Arrays;

public final class MyStringBufferPro implements IStringBuffer {
	private int LastIndex;
	private char[]data;
	private int memoryLength = 20;
	public MyStringBufferPro()
	{
		LastIndex = 0;
		data = new char[memoryLength];
	}	
	public MyStringBufferPro(String str)
	{
		data = str.toCharArray();
		LastIndex = str.length();
	}
	public MyStringBufferPro(char c)
	{
		LastIndex = 0;
		data = new char[memoryLength];
		append(c);
	}
	public MyStringBufferPro(int memoryLength)
	{
		this();
		this.memoryLength = memoryLength;
	}
	@Override
	public void append(String str) throws IndexIsNagetiveException, IndexIsOutofRangeException {
		// TODO Auto-generated method stub
		insert(LastIndex,str);
	}

	@Override
	public void append(char c) {
		// TODO Auto-generated method stub
		checkSpaceEnough(1);
		data[LastIndex] = c;
		moveNext();
	}
	public void append(char[] cs) {
		if(cs==null)return;
		// TODO Auto-generated method stub
		for (char c : cs) {
			append(c);
		}
	}
	private void moveNext()
	{
		LastIndex++;
		checkSpaceEnough(1);
	}
	@Override
	public void append(String... strs) throws IndexIsNagetiveException, IndexIsOutofRangeException {
		// TODO Auto-generated method stub
		for (String str : strs) {
			append(str);
		}
	}

	@Override
	public void insert(int pos, char c) throws IndexIsNagetiveException, IndexIsOutofRangeException {
		// TODO Auto-generated method stub
		insert(pos,String.valueOf(c));

	}

	@Override
	//核心方法,插入功能
	public void insert(int pos, String str) throws IndexIsNagetiveException, IndexIsOutofRangeException {
		if(checkIndexValid(pos))return;
		if(str == null)throw new NullPointerException();
		if(str.isEmpty())return;
		int leng = str.length();
		checkSpaceEnough(leng);  //检查内存是否足够
		int l = data.length;
		System.arraycopy(data, pos, data, pos+leng, LastIndex-pos);  //插入点后数据整体右移
		char[]cs = str.toCharArray();
		System.arraycopy(cs, 0, data, pos, cs.length);  //插入字符串
		LastIndex+=leng;
	}
	private boolean checkIndexValid(int id) throws IndexIsNagetiveException,IndexIsOutofRangeException
	{
		if(id<0||id>data.length-1||id>LastIndex)
		{
			if(id<0)throw new IndexIsNagetiveException("Exception:索引不得小于0");
			if(id>LastIndex)throw new IndexIsOutofRangeException("Exception:索引越界,大于数组的 边界或大于有效位置");
			return false;
		}
		return false;
	}
	private void checkSpaceEnough(int addLength)//检查内存是否足够,不够则扩充内存
	{
		if(LastIndex+addLength>data.length)
		{
			int multiply = 1+(LastIndex+addLength+1)/memoryLength;
			memoryLength = multiply*memoryLength;
			char[]temps = new char[memoryLength];
			System.arraycopy(data, 0,temps, 0, LastIndex);
			data = temps;
			//System.out.println(memoryLength);
		}
		
	}
	@Override
	public void delete(int start) throws IndexIsNagetiveException, IndexIsOutofRangeException{
		// TODO Auto-generated method stub  Arrays.copyOfRange(data, 0, start);
		checkIndexValid(start);
		char[]head = new char[memoryLength*(int)Math.ceil((float)(start+1)/memoryLength)];
		System.arraycopy(data, 0, head, 0, start);
		data = head;
		LastIndex = start;
	}
	@Override
	public void delete(int start, int end) throws IndexIsNagetiveException, IndexIsOutofRangeException {
		// TODO Auto-generated method stub
		checkIndexValid(start,end);
		char[]head = new char[memoryLength*(int)Math.ceil((float)(1+start+LastIndex-end+1)/memoryLength)];
		System.arraycopy(data, 0, head, 0, start);
		if(end<LastIndex-1)
		System.arraycopy(data, end+1, head, start, LastIndex-end-1);
		data = head;
		LastIndex = start+LastIndex-end-1;
		
	}
	private boolean checkIndexValid(int start,int end) throws IndexIsNagetiveException, IndexIsOutofRangeException
	{
		boolean res = true;
		res = res&&checkIndexValid(start);
		res = res&&checkIndexValid(end);
		if(start>=end)
		{
			res = false;
			throw new IndexIsNagetiveException("Exception:待删除的起始位置需在结束位置之前,不得大于等于结束位置");
		}
		return res;
	}
	public void clear()
	{
		data = new char[data.length];
		LastIndex = 0;
	}
	@Override
	public void reverse() {
		// TODO Auto-generated method stub
		char[]temp = Arrays.copyOfRange(data, 0, LastIndex);
		for (int i = temp.length-1; i >= 0; i--) {
			data[i] = temp[temp.length-1-i];
		}
	}

	@Override
	public int length() {
		// TODO Auto-generated method stub
		return this.data.length;
	}
	@Override
	public String toString()
	{
		char[]arr = Arrays.copyOfRange(data, 0, LastIndex);
		return new String(arr);
	}

}

---------------------------下一个类-------------------------------------------------------

package j2se;

public class IndexIsOutofRangeException extends Exception {

	private String Message;
	public IndexIsOutofRangeException()
	{
		super("Exception:索引超出内存的最大范围");
		this.Message = "Exception:索引超出内存的最大范围";

	}
	public IndexIsOutofRangeException(String message)
	{
		super(message);
		this.Message = message;
	}
}

---------------------------下一个类-------------------------------------------------------

package j2se;

public class IndexIsNagetiveException extends Exception {
	private String Message;
	public IndexIsNagetiveException()
	{
		super("Exception:索引不合理");
		this.Message = "Exception:索引不合理";

	}
	public IndexIsNagetiveException(String message)
	{
		super(message);
		this.Message = message;
	}

}


主方法调用
public static void main(String[]args) throws IndexIsNagetiveException, IndexIsOutofRangeException
	{
		MyStringBufferPro msbf = new MyStringBufferPro();
		msbf.append("0123456");
		System.out.println(msbf);
		//测试异常捕获
		testOutOfBoundExcpetion(msbf);
		testNagetiveIndexExcption(msbf);
		testDeleteExcption(msbf);

	}
	private static void testOutOfBoundExcpetion(MyStringBufferPro msbf)
	{
		try {
			msbf.insert(msbf.length(), "a");//索引越界异常
		} catch (IndexIsNagetiveException | IndexIsOutofRangeException e) {
			e.printStackTrace();
			System.out.println("异常原因:"+e.getMessage());
		}
	}
	private static void testNagetiveIndexExcption(MyStringBufferPro msbf)
	{
		try {
			msbf.insert(-1, "a");//索引小于0异常
		} catch (IndexIsNagetiveException | IndexIsOutofRangeException e) {
			e.printStackTrace();
			System.out.println("异常原因:"+e.getMessage());
		}
	}
	private static void testDeleteExcption(MyStringBufferPro msbf)
	{
		try {
			msbf.delete(3,2);//起始位置大于结束位置,删除错误
		} catch (IndexIsNagetiveException | IndexIsOutofRangeException e) {
			e.printStackTrace();
			System.out.println("异常原因:"+e.getMessage());
		}
	}

结果如下:
0123456
j2se.IndexIsOutofRangeException: Exception:索引越界,大于数组的 边界或大于有效位置
	at j2se.MyStringBufferPro.checkIndexValid(MyStringBufferPro.java:90)
	at j2se.MyStringBufferPro.insert(MyStringBufferPro.java:74)
	at j2se.HelloWorld.testOutOfBoundExcpetion(HelloWorld.java:36)
	at j2se.HelloWorld.main(HelloWorld.java:28)
异常原因:Exception:索引越界,大于数组的 边界或大于有效位置

j2se.IndexIsNagetiveException: Exception:索引不得小于0
	at j2se.MyStringBufferPro.checkIndexValid(MyStringBufferPro.java:89)
	at j2se.MyStringBufferPro.insert(MyStringBufferPro.java:74)
	at j2se.HelloWorld.testNagetiveIndexExcption(HelloWorld.java:45)
	at j2se.HelloWorld.main(HelloWorld.java:29)
异常原因:Exception:索引不得小于0

j2se.IndexIsNagetiveException: Exception:待删除的起始位置需在结束位置之前,不得大于等于结束位置
	at j2se.MyStringBufferPro.checkIndexValid(MyStringBufferPro.java:137)
	at j2se.MyStringBufferPro.delete(MyStringBufferPro.java:120)
	at j2se.HelloWorld.testDeleteExcption(HelloWorld.java:54)
	at j2se.HelloWorld.main(HelloWorld.java:30)
异常原因:Exception:待删除的起始位置需在结束位置之前,不得大于等于结束位置





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2023-06-07 练习-自定义异常
起个名




异常
加载中
public class MyStringBuffer implements IStringBuffer {
	
	//...
	
	class IndexIsNagetiveException extends Exception{
		public IndexIsNagetiveException() {}
		
		public IndexIsNagetiveException(String msg) {
			super(msg);
		}
	}
	
	class IndexOutofRangeException extends Exception{
		public IndexOutofRangeException() {}
		
		public IndexOutofRangeException(String msg) {
			super(msg);
		}
	}
	
	@Override
	public void append(String str) throws IndexIsNagetiveException, IndexOutofRangeException {
		insert(length,String.valueOf(str));
		
	}

	@Override
	public void append(char c) throws IndexIsNagetiveException, IndexOutofRangeException {
		append(String.valueOf(c));
	}

	@Override
	public void insert(int pos, char b) throws IndexIsNagetiveException, IndexOutofRangeException {
		insert(pos,String.valueOf(b));
	}

	@Override
	public void insert(int pos,String b) throws IndexIsNagetiveException, IndexOutofRangeException {
		// 边界条件判断
		if(pos < 0) 
			throw new IndexIsNagetiveException(String.valueOf(pos) + "位置下标为负异常");
		
		if(pos > length)
			throw new IndexOutofRangeException(String.valueOf(pos) + "位置下标超出范围异常");
		
		if(null == b)
			throw new NullPointerException(String.valueOf(pos) + "位置空指针指向异常");
		
		//扩容
		while(length + b.length() > capacity) {
			capacity = (int)((length + b.length())*1.5f);
			char[] newValue = new char[capacity];
			System.arraycopy(value, 0, newValue, 0, length);
			value = newValue;
		}
		
		char[] cs = b.toCharArray();
		
		//
		char[] nValue = new char[capacity];		
		if(pos > 0) 
		System.arraycopy(value, 0, nValue, 0, pos);
		System.arraycopy(value, pos, nValue, pos + cs.length, length - pos);
		//
		System.arraycopy(cs, 0, nValue, pos, cs.length);
		value = nValue;
		length = length + cs.length;
	}

	@Override
	public void delete(int start) throws IndexIsNagetiveException, IndexOutofRangeException {
		delete(start, length - 1);
	}

	@Override
	public void delete(int start, int end) throws IndexIsNagetiveException, IndexOutofRangeException {
		//边界条件判断
		if(start < 0)
			throw new IndexIsNagetiveException(String.valueOf(start) + "位置下标为负异常");
		
		if(start > length)
			throw new IndexOutofRangeException(String.valueOf(start) + "位置下标超出范围异常");
		
		if(end < 0)
			throw new IndexIsNagetiveException(String.valueOf(end) + "位置下标为负异常");;
		
		if(end <= start)
			throw new IndexOutofRangeException(String.valueOf(start) + "位置下标超出范围异常");
		
		System.arraycopy(value, end + 1, value, start, length - end - 1);
		length -= end + 1 - start;
	}

	
	public static void main(String[] args) {
		String str = rantoString(10);
		MyStringBuffer sb = new MyStringBuffer(str);
		try {
            sb.insert(0,null);
            sb.insert(-1,"test");
            sb.insert(11,"test");
             
            sb.delete(-1, 1);
            sb.delete(6,5);
            sb.delete(11,0);
             
        } catch (Exception e) {
            // TODO: handle exception
            if(e instanceof NullPointerException)
                System.out.println("出现空指针异常");
            if(e instanceof IndexIsNagetiveException | e instanceof IndexOutofRangeException )
                System.out.println("出现下标异常");      
            e.printStackTrace();
        }
	}
}

public interface IStringBuffer {
	public void append(String str) throws IndexIsNagetiveException, IndexOutofRangeException;	//追加字符串
	public void append(char c) throws IndexIsNagetiveException, IndexOutofRangeException;	//追加字符
	public void insert(int pos,char b) throws IndexIsNagetiveException, IndexOutofRangeException;	//指定位置插入字符
	public void insert(int pos,String b) throws IndexIsNagetiveException, IndexOutofRangeException;	//指定位置插入字符串
	public void delete(int start) throws IndexIsNagetiveException, IndexOutofRangeException;	//从开始位置删除剩下的
	public void delete(int start, int end) throws IndexIsNagetiveException, IndexOutofRangeException;	//从开始位置删除结束位置-1
	//...
}
出现下标异常
character.MyStringBuffer$IndexOutofRangeException: 11位置下标超出范围异常
	at character.MyStringBuffer.insert(MyStringBuffer.java:70)
	at character.MyStringBuffer.main(MyStringBuffer.java:175)





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2022-11-13 为什么在方法声明时用throws抛出了异常,在方法体内还要再用throw抛出异常呢?
2021-11-26 练习答案
2021-04-13 编译出错:需要Throwable类。


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 36 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 中级-异常处理-自定义异常 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图