第五章、面向对象基础--中

内容

  • 构造器
  • this
  • eclipse

学习目标

  • 掌握构造器的声明与使用
  • 掌握this关键字的使用
  • 掌握包的定义和导入
  • 熟练eclipse的使用

第六章 面向对象基础–中(续)

6.2 构造器(Constructor)

构造器又称为构造方法,那是因为它长的很像方法。但是和方法还有有所区别的。

构造器的作用

​ 要创建一个类的实例对象,必须调用一个对象的构造器,来完成类的实例初始化过程。实例初始化过程就是为实例变量赋初始值的过程。

当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。

小贴士:无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。

构造方法的定义格式

【修饰符】 构造器名(){
    // 实例初始化代码
}
【修饰符】 构造器名(参数列表){
	// 实例初始化代码
}

代码如下:

public class Student {
	private String name;
	private int age;
	// 无参构造
  	public Student() {} 
 	// 有参构造
  	public Student(String n,int a) {
		name = n;
    	age = a; 
	}
    //此处其他代码省略
}

注意事项

  1. 构造器名必须与它所在的类名必须相同。
  2. 它没有返回值,所以不需要返回值类型,甚至不需要void
  3. 如果你不提供构造器,系统会给出无参数构造器,并且该构造器的修饰符默认与类的修饰符相同
  4. 如果你提供了构造器,系统将不再提供无参数构造器,除非你自己定义。
  5. 构造器是可以重载的,既可以定义参数,也可以不定义参数。
  6. 构造器不能被static、final、synchronized、abstract、native修饰

练习

(1)声明一个员工类,

  • 包含属性:编号、姓名、薪资、性别,要求属性私有化,提供get/set,
  • 提供无参构造器和有参构造器
  • 提供getInfo()

(2)在测试类的main中分别用无参构造和有参构造创建员工类对象,调用getInfo

class Test02_Constructor_Exer{
	public static void main(String[] args){
		//分别用无参构造和有参构造创建对象,调用getInfo
		Employee e1 = new Employee();
		System.out.println(e1.getInfo());
		
		Employee e2 = new Employee("1001","张三",110000,'男');
		System.out.println(e2.getInfo());
		
		e2.setSalary(120000);
		System.out.println(e2.getInfo());
		
		System.out.println("e1薪资:" + e1.getSalary());
	}
}
class Employee{
	private String id;
	private String name;
	private double salary;
	private char gender;
	
	//提供无参构造器和有参构造器
	Employee(){
		
	}
	Employee(String i, String n){
		id = i;
		name = n;
	}
	Employee(String i, String n, double s, char g){
		id = i;
		name = n;
		salary = s;
		gender = g;
	}
	
	//提供get/set,
	public void setId(String i){
		id = i;
	}
	public String getId(){
		return id;
	}
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	public void setSalary(double s){
		salary = s;
	}
	public double getSalary(){
		return salary;
	}
	public void setGender(char g){
		gender = g;
	}
	public char getGender(){
		return gender;
	}
	
	//提供getInfo()
	public String getInfo(){
		return "编号:" + id + ",姓名:" + name + ",薪资:" + salary + ",性别:" +gender;
	}
	
}

6.3 this关键字

我们发现 setXxx 方法中的形参名字和构造器的形参名称并不符合见名知意的规定,那么如果修改与成员变量名一致,会怎么样呢?代码如下:

public class Student {
	private String name;
	private int age;

	public Student(String name, int age) {
		name = name;
		age = age;
	}

	public void setName(String name) {
		name = name;
	}

	public void setAge(int age) {
		age = age;
	}
}

经过修改和测试,我们发现新的问题,成员变量赋值失败了。也就是说,在修改了setXxx() 的形参变量名后,方法并没有给成员变量赋值!这是由于形参变量名与成员变量名重名,导致成员变量名被隐藏,方法中的变量名,无法访问到成员变量,从而赋值失败。所以,我们只能使用this关键字,来解决这个重名问题。

this的含义

this代表当前对象的引用(地址值),即对象自己的引用。

  • this可以用于构造器中:表示正在创建的那个实例对象,即正在new谁,this就代表谁
  • this用于实例方法中:表示调用该方法的对象,即谁在调用,this就代表谁。

this使用格式

1、this.成员变量名

当方法的局部变量与当前对象的成员变量重名时,就可以在成员变量前面加this.,如果没有重名问题,就可以省略this.

this.成员变量名;

2、this.成员方法

调用当前对象自己的成员方法时,都可以加"this.",也可以省略,实际开发中都省略

【变量=】this.成员方法(【实参列表】);

3、this()或this(实参列表)

当需要调用本类的其他构造器时,就可以使用该形式。

要求:

必须在构造器的首行

如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(【实参列表】)",否则会发生递归调用死循环

练习

(1)声明一个员工类,

  • 包含属性:编号、姓名、薪资、性别,要求属性私有化,提供get/set,
  • 提供无参构造器和有参构造器
  • 提供getInfo()

(2)在测试类的main中分别用无参构造和有参构造创建员工类对象,调用getInfo


6.4 标准JavaBean

JavaBean 是 Java语言编写类的一种标准规范。符合JavaBean 的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,成员变量私有化,并提供用来操作成员变量的setget 方法。

public class ClassName{
  //成员变量
    
  //构造方法
  	//无参构造方法【必须】
  	//有参构造方法【建议】
  	
  //getXxx()
  //setXxx()
  //其他成员方法
}

编写符合JavaBean 规范的类,以学生类为例,标准代码如下:

public class Student {
	// 成员变量
	private String name;
	private int age;

	// 构造方法
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// get/set成员方法
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
    
    //其他成员方法列表
    public String getInfo(){
        return "姓名:" + name + ",年龄:" + age;
    }
}

测试类,代码如下:

public class TestStudent {
	public static void main(String[] args) {
		// 无参构造使用
		Student s = new Student();
		s.setName("柳岩");
		s.setAge(18);
		System.out.println(s.getName() + "---" + s.getAge());
        System.out.println(s.getInfo());

		// 带参构造使用
		Student s2 = new Student("赵丽颖", 18);
		System.out.println(s2.getName() + "---" + s2.getAge());
        System.out.println(s2.getInfo());
	}
}

6.5 包(Package)

6.5.1 包的作用

1、可以避免类重名

有了包之后,类的全名称就变为:包.类名

2、分类组织管理众多的类

例如:

  • java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和Thread等,提供常用功能
  • java.net----包含执行与网络相关的操作的类和接口。
  • java.io ----包含能提供多种输入/输出功能的类。
  • java.util----包含一些实用工具类,如集合框架类、日期时间、数组工具类Arrays,文本扫描仪Scanner,随机值产生工具Random。
  • java.text----包含了一些java格式化相关的类
  • java.sql和javax.sql----包含了java进行JDBC数据库编程的相关类/接口
  • java.awt和java.swing----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

3、可以控制某些类型或成员的可见范围

如果某个类型或者成员的权限修饰缺省的话,那么就仅限于本包使用

6.5.2 声明包的语法格式

package 包名;

注意:

(1)必须在源文件的代码首行

(2)一个源文件只能有一个声明包的语句

包的命名规范和习惯:
(1)所有单词都小写,每一个单词之间使用.分割
(2)习惯用公司的域名倒置

例如:com.atguigu.xxx;

建议大家取包名时不要使用“java.xx"包

6.5.3 如何编译和运行(了解,之后在eclipse中就不用了)

编译格式:

javac -d class文件存放路径 源文件路径名.java

例如:

package com.atguigu.demo;

public class TestPackage {
	public static void main(String[] args) {
		System.out.println("hello package");
	}
}

编译:

javac -d . TestPackage.java

其中 . 表示在当前目录生成包目录

运行:

java com.atguigu.demo.TestPackage

定位到com目录的外面才能正确找到这个类

使用类的全名称才能正确运行这个类

[外链图片转存失败(img-QsPghIXL-1562938020762)(imgs/1561887467445.png)]

6.5.4 使用其他包的类

前提:被使用的类或成员的权限修饰符是>缺省的

(1)使用类型的全名称

例如:java.util.Scanner input = new java.util.Scanner(System.in);

(2)使用import 语句之后,代码中使用简名称

import语句告诉编译器到哪里去寻找类。

import语句的语法格式:

import 包.类名;
import 包.*;
import static 包.类名.静态成员; //后面补充

注意:

使用java.lang包下的类,不需要import语句,就直接可以使用简名称

import语句必须在package下面,class的上面

当使用两个不同包的同名类时,例如:java.util.Date和java.sql.Date。一个使用全名称,一个使用简名称

示例代码:

package com.atguigu.bean;

public class Student {
	// 成员变量
	private String name;
	private int age;

	// 构造方法
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// 成员方法
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
}
package com.atguigu.test;

import java.util.Scanner;
import java.util.Date;
import com.atguigu.bean.Student;

public class Test{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        Date now = new Date();
        java.sql.Date d = new java.sql.Date(346724566);
        
        Student stu = new Student();
        
        String str = "hello";
    }
}

IDE开发工具之一:eclipse的使用

1、概述

Eclipse是一个IDE(集成开发环境),集成了代码编写功能,分析功能,编译功能,调试功能等一体化的开发软件。

  • 免费
  • Java语言编写
  • 免安装
  • 扩展性强

下载和安装

[外链图片转存失败(img-YsmtabeJ-1562938020765)(imgs/1561888259871.png)]

版本代号 平台版本 需要的JDK最低版本
Galileo(伽利略) 3.5 JDK1.5
Helios(太阳神) 3.6 JDK1.5
Indigo(靛蓝) 3.7 JDK1.5
Juno(朱诺,天后) 3.8及4.2 JDK1.5
Kepler(开普勒) 4.3 JDK1.6
Luna(月神) 4.4 JDK1.6
Mars(火星) 4.5 JDK1.7
Neon(霓虹灯) 4.6 JDK1.8
Oxygen(氧气) 4.7 JDK1.8
Photon(光子) 4.8 JDK1.8
Eclipse 2018-09 4.9
Eclipse 2018-12 4.10
Eclipse 2019-03 4.11
Eclipse 2019-06 4.12

2、工作空间workspace

1、eclipse的管理层次

工作空间:存放项目代码等、其中的.metadata目录中是eclipse关于本工作空间的个性化配置文件、插件

eclipse中管理层次是:工作空间 》 项目 》 包 》 类等

一个工作空间可以有很多的项目,但是项目之间是互相独立的,一个项目不能使用另一个项目中的类等

一个项目可以有很多的包,不同包之间的类可以通过导包方式互相使用

一个包中可以有很多的类

2、指定工作空间

[外链图片转存失败(img-YN406KuZ-1562938020767)(imgs/1561890309548.png)]

如果想取消默认进入某个工作空间,可以把下面的选项勾上:

[外链图片转存失败(img-AP4wLOPB-1562938020768)(imgs/1561890607890.png)]

3、如何切换工作空间

[外链图片转存失败(img-D4O8mGBo-1562938020770)(imgs/1561890645215.png)]

4、设置工作空间字符编码等

[外链图片转存失败(img-AKORE2xF-1562938020771)(imgs/1561890703209.png)]

3、界面介绍

基本界面介绍

[外链图片转存失败(img-q2ks0EYa-1562938020773)(imgs/1561891074003.png)]

左边的导航区域:

  • navigation:导航器
  • package explorer:包资源管理器(建议初学者开发时选择使用这个,更紧凑一些)
  • project explorer:项目资源管理器

如何打开各种小窗口

[外链图片转存失败(img-g8PLIj13-1562938020773)(imgs/1561891301966.png)]

如何快速恢复界面布局

当界面中各种小窗口乱了,如何快速恢复如初:

[外链图片转存失败(img-TQkdS6oe-1562938020775)(imgs/1561891380329.png)]

4、设置字体

Window -> Preferences -> General -> Appearance -> Colors and Fornts,只需修改 Basic 里面的 Text Font 就可以了

[外链图片转存失败(img-YE24qnRE-1562938020776)(imgs/1561891510783.png)]

5、设置编辑区域背景颜色

[外链图片转存失败(img-vJWSQlYH-1562938020776)(imgs/1561891546079.png)]

[外链图片转存失败(img-SURmluuo-1562938020778)(imgs/1561891555248.png)]

6、设置控制台相关颜色

[外链图片转存失败(img-Nyn0xy0F-1562938020779)(imgs/1561893889624.png)]

7、创建项目

File菜单–》New --》Java Project

[外链图片转存失败(img-z7PVuLn0-1562938020780)(imgs/1561893130004.png)]

[外链图片转存失败(img-qUoReNxe-1562938020780)(imgs/1561893146305.png)]

[外链图片转存失败(img-jC9AlTQH-1562938020781)(imgs/1561893155487.png)]

8、创建类等

[外链图片转存失败(img-Uh0ORDWD-1562938020783)(imgs/1561893207513.png)]

[外链图片转存失败(img-mhoFFR9Y-1562938020783)(imgs/1561893356217.png)]

9、运行Java程序

要作为Java程序运行,该类必须包含main方法,而且在eclipse中,包含主方法的类必须与源文件名相同

三种方式运行Java程序

(1)工具栏选择绿色运行按钮 --> Run As --> Java Application

(2)菜单栏选择运行Run菜单 --> Run As --> Java Application

(3)光标定位到main所在的代码中,右键 --> Run As --> Java Application

(4)光标定位到main所在的代码中,快捷键Ctrl + F11

10、显示与隐藏行号

[外链图片转存失败(img-HVKP2jaQ-1562938020784)(imgs/1561892934816.png)]

如果发现已经√上了,还是看不见,有可能你把行号的颜色与背景颜色设置成一样了

[外链图片转存失败(img-qVJAdRmH-1562938020785)(imgs/1561893016467.png)]

11、导入项目

File菜单–》import–》找到General展开,并找到Existing Projects into Workspace点击next,然后选择你要导入的项目

[外链图片转存失败(img-FAWeoEUQ-1562938020786)(imgs/1561894086537.png)]

如何解决导入项目重名问题

[外链图片转存失败(img-R3OEQd6w-1562938020787)(imgs/1561893998844.png)]

打开要导入的项目目录,找到.project项目配置文件,修改新项目名

[外链图片转存失败(img-QGgPEwmW-1562938020788)(imgs/1561894031054.png)]

[外链图片转存失败(img-mvDqAijU-1562938020788)(imgs/1561894059598.png)]

12、用工作集管理众多的项目

当工作空间的项目特别多时,可以分类管理项目。这个时候就需要用到working set

[外链图片转存失败(img-j5SBM4oR-1562938020789)(imgs/1561894362055.png)]

[外链图片转存失败(img-5wsNRBsr-1562938020790)(imgs/1561894383260.png)]

[外链图片转存失败(img-1qx4sRyN-1562938020791)(imgs/1561894408653.png)]

[外链图片转存失败(img-0XKd2K3c-1562938020792)(imgs/1561894628657.png)]

13、快捷键

软件通用的快捷键

  • 保存:Ctrl + S
  • 剪切:Ctrl + X
  • 粘贴:Ctrl + V
  • 复制:Ctrl + C
  • 全选:Ctlr + A
  • 撤销:Ctrl + Z
  • 反撤销:Ctrl + Y
  • 查找与替换:Ctrl + F (find)

Eclipse的快捷键

  • 内容提示帮助:Alt + /
  • 快速单词补全:Ctrl + Alt + /
  • 方法形参列表提醒:Alt + Shift + /
  • 快速帮助:Ctrl + 1
    • 快速把一个语句结果赋值给一个变量(assign statement to new local variable)
    • 编译错误快速提示修改建议
  • 快速导包:Ctrl + Shift + O
  • 快速复制一行:
    • 向下复制一行:Ctrl + Alt + ↓
    • 向上复制一行:Ctrl + Alt + ↑
  • 交换两行:
    • 与上一行交换:Alt + ↑
    • 与下一行交换:Alt + ↓
  • 删除一行或选择的多行:Ctrl + D (delete)
  • 注释:
    • 单行注释与取消单行注释:Ctrl +/
    • 多行注释:Ctrl + Shift + /
    • 取消多行注释:Ctrl +Shift + \
  • 快速格式化:Ctrl +Shift + F(format)
  • 快速插入一行编辑
    • 在光标的下一行插入一个空行:Shift+回车
    • 在光标上一行插入新航开始编辑:Ctrl + Shift + 回车
  • 多行编辑:Alt + Shift + A 再按一次退出多行编辑模式
  • 弹出自动生成代码的菜单选择,包括自动生成构造器、get/set、equals、toString等:Alt + Shift + S
  • [外链图片转存失败(img-ZdC8YcJX-1562938020792)(imgs/1561896969070.png)]
  • 弹出包围当前代码的结构选择,包括for,while,try…catch等:Alt+Shift+Z
  • 快速给类、变量、方法等重命名:Alt +Shift + R (rename)
  • 将选中代码封装到一个新方法中:Alt + Shift +M (method)
  • 打开某个类型的源代码:Ctrl+Shift+T + 输入类型名
  • 代码跟踪:Ctrl+点击某个类或方法
  • 回到刚刚的位置:Alt+<–
  • 快速查看某类的继承关系图:选择某个类型后Ctrl+T
  • 打开某个类型成员列表图:Ctrl + O (outline)
  • 打开的多个源文件切换:Alt + ←, Alt + →
  • ​ Ctrl + PgUp,Ctrl + PgDown

自定义eclipse快捷键

[外链图片转存失败(img-Frx7J2NJ-1562938020793)(imgs/1561895047600.png)]

例如:自定义快速合拢和展开所有方法体的快捷键

collapse all(合拢):Ctrl + Shift + PgUP

expand all(展开):Ctrl + Shift + PgDn

14、快速开发模板

1、main方法:main + Alt + / 选择main方法后回车

2、System.out语句:sysout + Alt + / + 选择sysout回车

3、for循环:for + Alt + / + 选择for回车

4、switch结构:switch + Alt + / + 选择switch

定义自己的开发模板

例如:sop ==> System.out.print();

[外链图片转存失败(img-oMjakwfk-1562938020794)(imgs/1561896566825.png)]

15、修改代码风格

在创建类时,自动创建构造器和main等时,方法体中有

[外链图片转存失败(img-JqnxhBu2-1562938020794)(imgs/1561897053781.png)]

如何去掉呢?

windows–>Preferences -->Java–>Code Style -->Code Template --> Code --> xxx body -->把不要的去掉

[外链图片转存失败(img-cVGPxEkR-1562938020796)(imgs/1561897071449.png)]

[外链图片转存失败(img-OcyoaFIb-1562938020796)(imgs/1561897093178.png)]

16、Debug

在所有调试中,调试一个Java程序是最简单的,主要有设置断点、启动调试、单步执行、结束调试几步。

1)设置断点:在源代码文件中,在想要设置断点的代码行的前面的标记行处,双击鼠标左键就可以设置断点[外链图片转存失败(img-hSu3XC0U-1562938020796)(file:///C:\Users\Irene\AppData\Local\Temp\ksohtml5064\wps1.jpg)],在相同位置再次双击即可取消断点。

2)启动调试:Eclipse提供四种方式来启动程序(Launch)的调试,分别是通过菜单(Run –> Debug)、图标(“绿色臭虫”[外链图片转存失败(img-sG7GPWX6-1562938020797)(file:///C:\Users\Irene\AppData\Local\Temp\ksohtml5064\wps2.jpg)])、右键->Debug As以及快捷键(F11),在这一点上,与其他命令(例如Run)类似。

弹出提示,需要切换到调试(Debug)工作区,然后点击【Yes】。

[外链图片转存失败(img-8HpeeHFB-1562938020798)(imgs/1561897186844.png)]

[外链图片转存失败(img-PiWx21g4-1562938020799)(imgs/1561897265517.png)]

Debug小工具

[外链图片转存失败(img-FIjr2rhp-1562938020800)(imgs/1561897307916.png)]

1.表示从当前位置继续运行直到下一个断点,快捷键为F8。

2.表示打断整个进程,结束整个程序。

3.表示进入当前方法,快捷键为F5。

4.表示运行下一行代码,快捷键为F6。单步调试。

5.表示退出当前方法,返回到调用层,快捷键为F7。

6.表示当前线程的堆栈,从中可以看出在运行哪些代码,并且整个调用过程,以及代码行号。

17、练习eclipse的使用

练习1:

1、设置eclipse的工作空间workspace,这就是以后存放你在eclipse中编写的代码的目录

2、设置eclipse当前工作空间的字符编码为UTF-8

3、设置自己喜欢的字体颜色

4、创建工作集:teacher_code(存放老师的项目代码),self_code(存放自己上课练习的代码),homework(存放作业代码),project(存放项目代码)等

5、自定义快速合拢和展开所有方法体的快捷键

collapse all(合拢):Ctrl + Shift + PgUP

expand all(展开):Ctrl + Shift + PgDn

6、自定义开发模板

sop: ==> System.out.print();

练习2

1、创建day09_eclipse_self的Java项目

2、创建包:com.atguigu.eclipse.demo

3、创建类:com.atguigu.eclipse.demo.TestEclipse类,并编写main方法,打印“hello eclipse"并运行

4、创建类:com.atguigu.bean.Person类,并包括属性:id,name,age,gender,并私有化,提供无参和有参构造,get/set方法

5、创建类:com.atguigu.test.TestPesron类,并编写main方法,并创建Person对象,打印显示对象信息

6、创建类:com.atguigu.test.TestInput类,并编写main方法,并用无参构造创建Person对象,然后用Scanner,从键盘输入各个信息,为Person对象属性赋值,并打印对象信息

7、创建类:com.atguigu.test.Count类,并编写public int sum(int n):用递归就1-n的累加和

8、创建类:com.atguigu.test.TestCount类,并编写main方法,在main中编写for循环,从1循环到10,

并在循环体中调用sum(i),打印结果,并用debug调试运行过程

9、创建类:com.atguigu.test.TestArray类,并编写main方法,在main中编写如下代码:

    public static void main(String[] args){
    	int[] arr = {3,6,2,8,4};
    	
    	for (int i = 1; i < arr.length; i++) {
			for (int j = 0; j <= arr.length-i; j++) {
				if(arr[j] > arr[j+1]){
					int temp =arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
    	
    	for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
    }

无参和有参构造,get/set方法

5、创建类:com.atguigu.test.TestPesron类,并编写main方法,并创建Person对象,打印显示对象信息

6、创建类:com.atguigu.test.TestInput类,并编写main方法,并用无参构造创建Person对象,然后用Scanner,从键盘输入各个信息,为Person对象属性赋值,并打印对象信息

7、创建类:com.atguigu.test.Count类,并编写public int sum(int n):用递归就1-n的累加和

8、创建类:com.atguigu.test.TestCount类,并编写main方法,在main中编写for循环,从1循环到10,

并在循环体中调用sum(i),打印结果,并用debug调试运行过程

9、创建类:com.atguigu.test.TestArray类,并编写main方法,在main中编写如下代码:

    public static void main(String[] args){
    	int[] arr = {3,6,2,8,4};
    	
    	for (int i = 1; i < arr.length; i++) {
			for (int j = 0; j <= arr.length-i; j++) {
				if(arr[j] > arr[j+1]){
					int temp =arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
    	
    	for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
    }

用Debug找出问题

上一篇:原生js实现图片懒加载


下一篇:.NET ORM框架 SqlSuagr4.0 功能详解与实践【开源】