0%

xlrd 是python环境下对excel中的数据进行读取的一个模板,可以进行的操作有:

  • 读取有效单元格的行数、列数
  • 读取指定行(列)的所有单元格的值
  • 读取指定单元格的值
  • 读取指定单元格的数据类型
1
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 78

调整ChromeDriver版本,下载chromedriver.exe放到Script文件夹下。

Code from JZ :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import xlrd
from selenium import webdriver
from time import sleep
from selenium.webdriver.support.ui import Select

subject = '基因'
lang = '中文'

# 读取excel中的信息, 然后根据信息爬虫
if __name__ == '__main__':
# 打开浏览器
url = 'http://www.hiresearch.cn/pcomp'
browser = webdriver.Chrome()
browser.get(url)
browser.maximize_window()
# 先添加两个搜索框
add_element = browser.find_element_by_xpath('//*[@id="logic_1"]/div[1]/a')
add_element.click()
add_element.click()
# 输入主题
subject_text = browser.find_element_by_xpath('//*[@id="TxtKeyword1"]')
subject_text.click()
subject_text.send_keys(subject)
# 语言全选按钮
all_lan = browser.find_element_by_xpath('//*[@id="searchForm"]/div[3]/div/div[4]/div[2]/div/div[1]/div/div/label')
all_lan.click()
# 中文按钮
ch = browser.find_element_by_xpath('//*[@id="lblcn"]')
ch.click()

# 选择类别
Select(browser.find_element_by_xpath('//*[@id="SltType2"]')).select_by_visible_text('基金名称')
Select(browser.find_element_by_xpath('//*[@id="SltType3"]')).select_by_visible_text('基金类别')

# 选择年份
browser.find_element_by_xpath('//*[@id="limit_bar"]').click()
browser.find_element_by_xpath('//*[@id="rangeYear"]').click()
# 读取信息
name = 'limit-pcy.xlsx'
wb = xlrd.open_workbook(filename=name) # 打开文件

sheet1 = wb.sheet_by_index(0) # 通过索引获取表格
type1s = sheet1.col_values(2) # 获取类别
type2s = sheet1.col_values(3) # 获取自类别
years = sheet1.col_values(4) # 年份
counts = sheet1.col_values(5) # 数量
i = 1
beq = 0
end = 0
while i < len(years):
type1 = type1s[i]
browser.find_element_by_xpath('//*[@id="TxtKeyword2"]').clear()
browser.find_element_by_xpath('//*[@id="TxtKeyword2"]').click()
browser.find_element_by_xpath('//*[@id="TxtKeyword2"]').send_keys(type1)
type2 = type2s[i]
if len(type2) > 0:
try:
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').clear()
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').click()
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').send_keys(type2)
except Exception:
add_element.click()
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').clear()
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').click()
browser.find_element_by_xpath('//*[@id="TxtKeyword3"]').send_keys(type2)
year = years[i]
if type(year) == float:
beq = end = int(year)
else:
ss = year.split('-')
beq = int(ss[0])
end = int(ss[1])
# 如果年份有-需要处理一下
Select(browser.find_element_by_xpath('//*[@id="SltBeginYear"]')).select_by_visible_text(str(beq))
Select(browser.find_element_by_xpath('//*[@id="SltEndYear"]')).select_by_visible_text(str(end))
# 开始检索
browser.find_element_by_xpath('//*[@id="btnsearch1"]').click()
count = int(counts[i])
sleep(2)
# 从1到count
for j in range((count + 99) // 100):
browser.find_element_by_xpath('//*[@id="tabExport"]').click()
Select(browser.find_element_by_xpath('//*[@id="modalExport"]')).select_by_visible_text('项目 + 所有成果')
browser.find_element_by_xpath('//*[@id="modalExportFrom"]').clear()
browser.find_element_by_xpath('//*[@id="modalExportFrom"]').click()
browser.find_element_by_xpath('//*[@id="modalExportFrom"]').send_keys(j * 100 + 1)

browser.find_element_by_xpath('//*[@id="modalExportTo"]').clear()
browser.find_element_by_xpath('//*[@id="modalExportTo"]').click()
if count >= j * 100 + 100:
browser.find_element_by_xpath('//*[@id="modalExportTo"]').send_keys(j * 100 + 100)
else:
browser.find_element_by_xpath('//*[@id="modalExportTo"]').send_keys(count)

browser.find_element_by_xpath('//*[@id="modalBtnExport"]').click()
sleep(3)
print(type1, type2, beq, end, count)
handle = browser.current_window_handle
handles = browser.window_handles
for newhandle in handles:
# 筛选新打开的窗口B
if newhandle != handle:
browser.switch_to_window(newhandle)
browser.close()
browser.switch_to_window(handle)
sleep(10)
i += 1

print('success!')

题目描述

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

题解

树的问题,递归解决。题目未说明是否会出现数值相同的节点

  1. 是左子树的子树;2. 是右子树的子树;3. 从根节点重合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
bool isSub(TreeNode* A, TreeNode* B)
{
//从根节点重合
if(B==NULL)return true;
if(A==NULL)return false;
if(A->val==B->val)
return isSub(A->left,B->left)&&isSub(A->right,B->right);
return false;
}
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
// "约定空树不是任意一个树的子结构"实际上不利于编程
if(B==NULL||A==NULL)return false;
return isSub(A,B) || isSubStructure(A->left,B) || isSubStructure(A->right,B);
}
};

题目描述

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

提示:对于 MySQL 解决方案,如果要转义用作列名的保留字,可以在关键字之前和之后使用撇号。例如 `Rank`

题解

1
select Score, DENSE_RANK() OVER(ORDER by Score DESC) as `Rank` from Scores

sql排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)

排号从1开始,都需要有 over (order by …) 子句。https://www.cnblogs.com/52xf/p/4209211.html

案例:

表结构和初始数据-晓菜鸟

ROW_NUMBER

根据over子句对某一列排序,按照over子句排序结果为查询出来的每一行记录生成一个序号,依次排号且不重复。

over子句与order by子句互不影响。如下sql语句,按照SubTime降序编号,结果按照TotalPrice降序返回:

1
select ROW_NUMBER() OVER(order by [SubTime] desc) as row_num, * from [Order] order by [TotalPrice] desc

可用于实现web分页。根据订单提交时间倒序排列获取第三至第五条数据:

1
2
3
4
5
with orderSection as
{
select ROW_NUMBER() OVER(order by [SubTime] desc) rownum, * from [Order]
}
select * from [orderSection] where rownum between 3 and 5 order by [SubTime] desc

RANK

rank函数对于over子句中排序字段值相同的记录生成相同的序号,后面的记录的排号是基于当前的记录数,即:同一组的序号是一样的,下一组的序号是:上一组的序号+上一组的记录的数量-1.

1
select RANK() OVER(order by [UserId]) as rank,* from [Order]

使用rank函数排名-晓菜鸟

DENSE_RANK

dense_rank与rank的区别在于dense_rank的排号是连续的,rank的排号可能不连续。在同一组中的记录排号相同。

1
select DENSE_RANK() OVER(order by [UserId]) as den_rank,* from [Order]

使用dense_rank函数排名-晓菜鸟

NTILE

ntile有一个参数用于指出桶数,将数据排序后进行装桶处理并编号。装桶及编号的规则:https://www.cnblogs.com/52xf/p/4209211.html

pm2和nodejs

nodejs是javascript的运行环境,异步IO,支持高并发。

PM2 (Process Manager 2) 是JavaScript运行时Node.js的进程管理器。

private、protected、public、static、final

对任何类、方法、参数、变量,严格控制访问范围,这样有利于模块解耦。

  • private should be used when something is not used outside of a given class
    • for methods and fields - when they are used only within the same class
    • for classes - only on nested classes, when used in the same class
  • protectedshould be used when
    • for methods and field - when you need to make them accessible to subclasses only
    • for classes - again only nested classes, accessible by subcalsses
  • public is used when something is accessible by every other class

  • static is used when you don’t need an instance of a class (i.e. object) to use it:

    • for fields - when you want to have a global field
    • for methods - when you need utility functions that do not depend on object state
    • for nested classes - when you want to access them without an instance of the enclosing class.
  • abstract when you don’t want to provide implementations in the current class:
    • on methods - when subclasses have to provide the actual implementation, but you want to invoke these methods (no matter how they are implemented) in this class.
    • on classes - to denote that the class may have abstract methods.
  • final when you don’t want something to change.
    • on fields, when you want to assign the value only once. It is useful when you want to pass a local variable to an inner class - you have to declare it final.
    • on classes and methods - when you don’t want subclasses to be able to extend / override them.

方法的访问修饰符:

img

题目描述

Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentIdDepartment 表包含公司所有部门的信息。编写一个 SQL 查询,找出每个部门获得前三高工资的所有员工。

题解

  1. 如何找出每个部门排名前三的工资值?两张Employee表做笛卡尔积,筛选留下同一部门的、工资不低于自己的记录,并且比自己工资高的数值不能小于3个。
1
2
select * from Employee as e1
where 3 > (select count(distinct e2.Salary) from Employee as e2 where e1.Salary < e2.Salary and e1.DepartmentId = e2.DepartmentId)
  1. 将 Employee 和 Department 合并
1
2
select d1.Name as Department, e1.Name as Employee, e1.Salary as Salary from Employee as e1, Department as d1
where e1.DepartmentId = d1.Id and 3 > (select count(distinct e2.Salary) from Employee as e2 where e1.Salary < e2.Salary and e1.DepartmentId = e2.DepartmentId)

Win10远程桌面 出现 身份验证错误,要求的函数不受支持

运行 gpedit.msc,本地组策略:计算机配置>管理模板>系统>凭据分配>加密Oracle修正

选择启用并选择易受攻击。

cmd 中输入:mstsc /admin /v:192.168.190.191

mstsc (Microsoft terminal services client) 创建与终端服务器或其他远程计算机的连接,编辑现有“远程桌面连接(.rdp)”配置文件,并将 Windows XP 连接,迁移到新的 .rdp 文件中。Microsoft Telnet Screen Control ,即“微软远程桌面控制”。

创建考勤用户-用户ID设置下拉菜单

数据库表与 model 对应。在创建考勤用户时,只显示未成为 atd_user 的 student 的 username. 在 dbis_user_student 表中取出所有 use_id,在 atd_user 表中取出所有的 uid, 求差集。得到 useId 的集合,到 user 表中查得 user 对象,将 userId 和 userName 存入数组,用 DropList 展示数据。

backend\models\AtdUser.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static function getRemainUsers()
{
$atdUsers = self::find()->select(["uid"])->all();
$atdUserIds=array();
for($i = 0; $i < count($atdUsers); $i++) {
// var_dump($atdUsers[$i]["uid"]);
$atdUserIds[] = $atdUsers[$i]["uid"];
}
$userStudents = \common\models\UserStudent::find()->select(["userid"])->all();
$userStudentIds=array();
for($i = 0; $i < count($userStudents); $i++) {
// var_dump($atdUsers[$i]["uid"]);
$userStudentIds[] = $userStudents[$i]["userid"];
}
$userIdList=array_diff($userStudentIds, $atdUserIds);

//根据userIdList从User表中取出姓名
$userList=User::findAll($userIdList);
// var_dump($userList);

foreach ($userList as $key => $user) {
$userDropList[$user['id']] = $user['username'];
}
// var_dump($userDropList);
// die();
return $userDropList;
}
PHP打印输出
1
2
var_dump($userStudents[1]['userid']);
die();

如果改了_form 的参数,其他用到该表格的地方的参数也需要修改。AtdUserController.php中,update 和 create 函数传递给 _form 的 userList 并不相同,create 可以直接调用 getRemainUsers(),update的 userList 应包含所有user,如果只是传入剩余的学生列表,下拉框中会默认显示数组的第一个值。

下拉列表默认选中不是在options参数里面决定的,而是$model->category的值决定的。

考勤页面 默认按照ccid排序

backend\views\attendance\atd-user\index.php 中使用了 GridView 组件来展示列表,在 backend\controllers\attendance\AtdUserController.php 的 actionIndex() 中创建 AtduserQuery 对象用于数据库查询,最后传入参数。

修改 backend\models\search\AtdUserQuery.php:

1
2
3
4
5
$dataProvider = new ActiveDataProvider([
'query' => $query,
// 新增配置项 默认 ccid 升序
'sort' => ['defaultOrder' => ['ccid' => SORT_ASC]],
]);

创建用户时报错 500,但能成功创建

1
2
3
4
5
#0 D:\xampp\htdocs\dbis_starter-kit\vendor\yiisoft\yii2\rbac\DbManager.php(835): yii\base\ErrorHandler->handleError(8, 'Trying to get p...', 'D:\\xampp\\htdocs...', 835, Array)
#1 D:\xampp\htdocs\dbis_starter-kit\common\models\User.php(293): yii\rbac\DbManager->assign(NULL, 165)
#2 D:\xampp\htdocs\dbis_starter-kit\backend\models\UserForm.php(126): common\models\User->afterSignup()
#3 D:\xampp\htdocs\dbis_starter-kit\backend\controllers\UserController.php(69): backend\models\UserForm->save()
#4 [internal function]: backend\controllers\UserController->actionCreate()

是因为数据库中没有 user 这个角色,因此 getRole() 返回了 NULL 值:

(afterSignup()函数)

1
2
3
4
5
// Default role
$auth = Yii::$app->authManager;

// if $auth->getRole(User::ROLE_USER) = NULL ?
$auth->assign($auth->getRole(User::ROLE_USER), $this->getId());

直接注释掉这两行。

另外,状态为 NOT Active 的用户无法登录。

题目描述

查询第N高的数据

题解

用到了limit、offset、ifnull等关键字的知识点。

1
2
3
4
5
6
SELECT 
column_list
FROM
table1
ORDER BY column_list
LIMIT row_count OFFSET offset;

row_count表明将要返回的行数。offset表明从开头要跳过的行数。

在MySQL中可以缩写:

1
2
3
4
5
6
SELECT 
employee_id, first_name, last_name
FROM
employees
ORDER BY first_name
LIMIT 3 , 5;
1
IFNULL(expression, alt_value)

IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值。

sql的 order by 默认为升序asc,desc是降序。

最终答案为:

1
2
3
4
5
6
7
8
9
10
11
12
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
set N=N-1;
RETURN (
# Write your MySQL query statement below.
select ifnull(
(select distinct Salary from Employee
order by Salary desc
limit N,1),
null)
);
END

在改bug时遇到了下面的问题:

当前页面:http://exploit.nkdbis.cn

原来的代码:

1
2
3
<h4 class="g-aline g-nav-lr-left l-title">
<a :href="'/article/' + item.id">{{item.title || item.name}}</a>
</h4>

点击链接显示:404 Not Found,查看请求:

1
2
3
4
5
Request URL: http://exploit.nkdbis.cn/article/8
Request Method: GET
Status Code: 404 Not Found
Remote Address: 39.106.204.28:80
Referrer Policy: strict-origin-when-cross-origin

将代码修改为:

1
2
3
<router-link :to="'/article/'+item.id">
<h4>{{item.title || item.name}}</h4>
</router-link>

再次请求,可以成功获得资源,查看请求:

1
2
3
4
5
Request URL: http://exploit.nkdbis.cn/api/front/article/8
Request Method: GET
Status Code: 200
Remote Address: 39.106.204.28:80
Referrer Policy: strict-origin-when-cross-origin

在此记录关于web页面跳转的知识点。

页面跳转

页面跳转有4种:jsp动作指令forward、html的超链接、重定向、response的响应跳转。

jsp动作指令forward

JSP(全称JavaServer Pages)是由Sun Microsystems公司主导建立的一种动态网页技术标准。 JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。

\jsp:forward转发,也是可以带参数,带值的。

· 静态中的格式:<jsp:forward page=”文件或标识路径的表达式”/>

· 动态中的格式:<jsp:forward page=”文件路径或标识路径的表达式”>
<jsp:param name=”参数名称1” value=”值1”/>
<jsp:param name=”参数名称2” value=”值2”/>
……
\</jsp:forward>

Forward(直接转发)是服务器直接请求资源,把内容响应给用户,这个过程只有一次请求,即只有一个request对象。Forward是一种服务器行为。

html的超链接

https://blog.csdn.net/cgl125167016/article/details/88973199#t5

重定向

通过修改http协议的header部分,对浏览器下达重定向指令的,让浏览器对在location中指定的url提出请求,使浏览器显示重定向网页的内容。

无论有没有设置基础路径,使用转发方式进行跳转的相对路径都是该文件的当前路径,而重定向跳转可以跳转到站点内或站点外的页面,所以使用绝对路径方式,“/”表示定位到服务器站点根目录。

Redirect(间接转发),是服务器反馈给浏览器让它重新再发起一次请求,这个过程中有两次请求,即有两个request对象。Redirect是一种客户端行为。

response的响应跳转

response是服务器对客户端的反馈,其对页面重定向的流程是:当客户端向服务器发起请求时,服务器重新给客户端一个URL地址,让客户端重新发起一个新的请求,在这个过程中,客户端第一次请求所携带的头信息将消失,在重定向之后而且地址栏显示的是重定向的页面,这是一种客户端行为。

可以通过sendRedirect重定向到服务器任何一个URL。若使用绝对路径,其中的根路径是服务器根目录,如URL=”/xxx”,则实际定向到http://localhost:8080/xxx。一般可使用request.getContextPath() + “/xxx”来访问webapp根目录下的资源。
注意:通过重定向无法访问WEB-INF中的资源,因为重定向是客户端行为,相当于浏览器重新输入URL,而WEB-INF中的内容无法通过输入URL来访问。


漏洞管理系统仍然存在的问题:

直接访问http://exploit.nkdbis.cn/index会报404:

1
2
3
4
5
Request URL: http://exploit.nkdbis.cn/index
Request Method: GET
Status Code: 404 Not Found
Remote Address: 39.106.204.28:80
Referrer Policy: strict-origin-when-cross-origin

访问http://exploit.nkdbis.cn时,网址栏中显示http://exploit.nkdbis.cn/index,但是请求中显示:

1
2
3
4
5
Request URL: http://exploit.nkdbis.cn/
Request Method: GET
Status Code: 200 OK
Remote Address: 39.106.204.28:80
Referrer Policy: strict-origin-when-cross-origin

暂时没明白是怎么回事。

题目描述

编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。

题解

动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int calculateMinimumHP(vector<vector<int>>& dungeon) {
//dp[i][j] 表示从 dp[i][j] 到达 目的地 时最少需要的 HP,应该从右下角推到左上角
//dp[i][j] = max(1, min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j])
int row = dungeon.size();
int col = dungeon[0].size();
int** dp = new int* [row];
for (int i = 0; i < row; i++) {
dp[i] = new int[col];
}
dp[row - 1][col - 1] = max(1, 1- dungeon[row - 1][col - 1]);
for (int i = row-2; i >= 0; i--) {
dp[i][col-1] = max(1, dp[i + 1][col-1] - dungeon[i][col-1]);
}
for (int j = col-2; j >= 0; j--) {
dp[row-1][j] = max(1, dp[row-1][j + 1] - dungeon[row-1][j]);
}
for (int i = row - 2; i >=0; i--) {
for (int j = col - 2; j >=0; j--) {
dp[i][j]= max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
}
}

//print the dp
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
cout << dp[i][j] << " ";
}
cout << endl;
}
return dp[0][0];
}

SSM/SSH框架

SSH是指 Struts2 Spring Hibernate三个框架。SSM是指SpringMVC Spring MyBatis。对于MVC框架,SSH是Structs2做controller,hibernate负责持久化层;SSM是SpringMVC做controller,MyBatis负责持久化层。Structs2是Action级别,SpringMVC是方法级别,更容易实现RESTful风格。

SSM和SSH的共同点:由Spring以来至如DI管理各层组件;使用面向切面编程AOP管理事务、日志、权限等。

后端编程

框架、负载均衡、灾难恢复、缓存、消息、分布式、搜索等。

Java动态代理

  1. 静态代理
  2. JDK动态代理
  3. CGLib动态代理

动态代理是JDK运行期间动态创建class字节码并加载的过程。

为什么要用Java动态代理?

类方法数量越来越多时,静态代理的代码量会十分庞大。

preview

Java动态代理只能对interface进行操作,不能对class操作:

class(非abstract)可以被实例化,interface不能被实例化,所有的interface变量都是通过向上转型并指向某个实例的。Java动态代理机制可以在运行期动态创建interface实例。

在运行期间动态创建一个interface实例:

  1. 定义InvocationHandler实例用于实现接口的方法调用;
  2. 通过Proxy.newProxyInstance()创建interface实例,需要三个参数:
    1. 接口类的ClassLoader;
    2. 需要实现的接口数组;
    3. InvocationHandler实例
  3. 将返回的Object转为接口类型。

动态字节码的生成

字节码

字节码通常指的是已经经过编译,但与特定机器代码无关,需要解释器转译后才能成为机器代码的中间代码。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。 字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机。 维基百科

ASM、CGLib

ASM 框架可以直接操作字节码,动态修改类和方法,CGLib (Code Generation Library,代码生成库) 底层也是由ASM实现。ASM将对代码的操作包装成一个访问者,在解析JVM加载到的字节码时调用。ClassReader 是 ASM 代码的入口,通过它解析二进制字节码,实例化时它时,我们需要传入一个 ClassVisitor,在这个 Visitor 里,我们可以实现 visitMethod() / visitAnnotation() 等方法,用以定义对类结构(如方法、字段、注解)的访问方法。而 ClassWriter 接口继承了 ClassVisitor 接口,我们在实例化类访问器时,将 ClassWriter “注入” 到里面,以实现对类写入的声明。(https://zhenbianshu.github.io/2018/11/control_jvm_byte_code.html)

CGLib 常应用于 AOP 框架,提供方法的拦截,加入相应的业务逻辑代码。

Java是静态语言,放到JVM中运行之前需要先进行编译。