这里使用阿里云ECS服务器Ubuntu20.04版本进行搭建

首先看看有哪些lamp的使用的较多,使用docker search lamp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# docker search lamp
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mattrayner/lamp A simple LAMP docker image running the prere… 285 [OK]
linode/lamp LAMP on Ubuntu 14.04.1 LTS Container 181
tutum/lamp Out-of-the-box LAMP image (PHP+MySQL) 148
fauria/lamp Modern, developer friendly LAMP stack. Inclu… 110 [OK]
greyltc/lamp a super secure, up-to-date and lightweight L… 103 [OK]
lioshi/lamp Docker image for LAMP under debian 14 [OK]
dgraziotin/lamp 11 [OK]
linuxconfig/lamp Automated build LAMP stack environment for f… 5 [OK]
jakubboucek/lamp-devstack-php Prepared images for local development in LAM… 5
thiagobarradas/lamp Use PHP (5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, … 4
lampson0505/ubuntu-phy An Ubuntu image with teamd for network inter… 3
shelleyma/lampp2 lampp from github 3 [OK]
lead4good/lamp-php LAMP Stack PHP 2 [OK]
...

这里我们使用第一个进行安装

1
2
3
4
5
6
7
8
9
10
11
# docker pull mattrayner/lamp
Using default tag: latest
latest: Pulling from mattrayner/lamp
35807b77a593: Pull complete
ccfecfa17ed6: Pull complete
499764c8dc6b: Pull complete
c6b0ddc4cdc0: Pull complete
...
Digest: sha256:f7caeba589eaea7e3d20f4ae3e3bf88233e66e7df59eb5adb49161a5365f9f90
Status: Downloaded newer image for mattrayner/lamp:latest
docker.io/mattrayner/lamp:latest

启用名字mylamp,以便以后可以直接使用名字重启

1
2
# docker run --name mylamp -p 80:80 -p 3306:3306 -d mattrayner/lamp
e9c27bbc28366f0b00018a03b0b31be2f1ac1f1355ea31796b970c312e7f17cf

测试运行结果

photo

查看dklamp中的mysql的root密码,使用命令

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
# docker logs mylamp
Updating for PHP 8.0
Replacing CLI php.ini values
Editing APACHE_RUN_GROUP environment variable
Editing phpmyadmin config
Setting up MySQL directories
Allowing Apache/PHP to write to the app
Allowing Apache/PHP to write to MySQL
Editing MySQL config
=> An empty or uninitialized MySQL volume is detected in /var/lib/mysql
=> Installing MySQL ...
=> Done!
=> Waiting for confirmation of MySQL service startup
=> Creating MySQL admin user with random password
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY ''' at line 1
=> Done!
========================================================================
You can now connect to this MySQL Server with 46W9QD9oC5Co

mysql -uadmin -p46W9QD9oC5Co -h<host> -P<port>

Please remember to change the above password as soon as possible!
MySQL user 'root' has no password but only allows local connections

enjoy!

查看密码为46W9QD9oC5Co,用户名为admin

docker常用命令

查看所有镜像:docker image ls
查看是否有容器在运行:docker ps
容器停止:docker stop mylamp
容器开始:docker start mylamp

本文采用阿里云ECS服务器实例来进行搭建docker环境

连接阿里云服务器

通过xshell或者其他shell工具连接阿里云服务器

使用APT安装

由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改。因此,我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书

1
2
3
4
5
6
7
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release

鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看

为了确认所下载软件包的合法性,需要添加软件源的 GPG 密钥

1
2
3
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 官方源
# $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

然后,我们需要向 sources.list 中添加 Docker 软件源

1
2
3
4
5
6
7
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 官方原
# $ echo \
# "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
# $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

以上命令会添加稳定版本的 Docker APT 镜像源,如果需要测试版本的 Docker 请将 stable 改为 test

使用官方安装脚本自动安装

在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 —mirror 选项使用国内源进行安装

1
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中

也可以使用国内 daocloud 一键安装命令:

1
curl -sSL https://get.daocloud.io/docker | sh

启动Docker

1
2
$ sudo systemctl enable docker
$ sudo systemctl start docker

建立docker用户组

默认情况下,docker 命令会使用 Unix socket与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组

建立docker

1
$ sudo groupadd docker

将当前用户加入docker

1
$ sudo usermod -aG docker $USER

退出当前终端并重新登录,进行如下测试

测试Docker是否安装正确

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
$ docker run --rm hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

文件上传

文件上传漏洞介绍

什么是文件上传漏洞

凡是存在文件上传的地方均有可能存在文件上传漏洞,关于上传文件操作的时候对方代码写的是否完整、是否安全,一旦疏忽了某个地方可能会造成文件上传漏洞

文件上传的原理

网站Web应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个Web可访问的目录上,并将恶意文件传递给如PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作。还有一部分是攻击者通过Web服务器的解析漏洞来突破Web应用程序的防护

文件上传漏洞的危害

文件可以自定义,可以成为webshell,通过文件上传来上传网站后门,直接获取网站权限,属于高危漏洞。上传漏洞与SQL注入或 XSS相比 , 其风险更大 。可以获取数据库信息,可以对服务器提权,获取内网权限

文件上传漏洞如何查找和判断

  1. 黑盒查找
    文件后台
    进入网站后台不一定获得网站权限,可以从后台获取网站权限
    会员中心
    通过图片上传
    文件扫描
    使用工具扫描出后台路径
  2. 白盒查找
    通过代码分析到上传漏洞
    查找文件上传功能

文件上传的实现

利用思路

利用思路

文件上传在实际应用中的方式

方式一

先直接传一个PHP,实战先传马
实战先传一个正常的图片,看看有无返回存储地址
如果能直接上传并解析,已离成功不远

方式二

先传一个shell,然后进行修改
connect-Type:image/jpeg,看看是否可以进行绕过,如果不行,在上传内容添加GIF89a
当然上传了还得看是否能够被解析为php,所有的上传都要考虑是否能够被解析

方式三

  • 上传一个abc.abcd,目的只是为了查看是否为白名单还是黑名单绕过。黑名单限制一般为此文件类型不允许上传,考虑双写,大小写,空格,php2,php3,php4,php5,pht,phtml,等方式
  • 我们继续上传一个/htaccess文件.htaccess文件能够设置服务器的解析文件的格式,匹配到dudu就已php的格式来解析,继而上传马
  • 如果说.htaccess不能上传,接下来上传一个.user.ini,继而上传一个马

方法四

如果白名单限制上传

  • 考虑00截断上传
  • 文件包含漏洞+图片马
  • 文件包含漏洞+二次渲染+图片马

方法五

上传的东西是否被服务器很快的删除或者移除,或者说上传成功,但是无法访问,就得考虑条件竞争
以上均不行,考虑逻辑层面的思路

文件上传常见验证

前端

JS类防护

后端

后缀名

黑名单:明确不允许上传的格式后缀,asp、php、jsp、aspx等。
白名单:明确可以上传的文件后缀。jpg、png、zip、gif等

文件类想

MIME信息:

Content-Type称之为MIME信息,通过伪造Content-Type等来进行上传

文件头

内容头信息

文件上传绕过

黑名单绕过

特殊解析信息

使用yijuhua.jpg.zip.php等多后缀,如果没有添加strrchr()、和deldot()的话可以绕过
deldot():删除文件名末尾的点,防止多后缀
strchr(string1,string2):查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符

如果php3、php5、phtml没有定义到黑名单中,且apache开启解析,则可以用这种格式进行绕过

.htaccess解析

仅存在于Apache中
htaccess文件时apache服务器中的一个配置文件,负责相关目录下的网页配置。通过htaccess文件,可以帮助我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

大小写绕过

对大小写进行强制转换,后缀修改大小写即可绕过

空格绕过

源码中缺少收尾去空函数,则可以通过加空格进行绕过
trim():去除字符串中的空格

点绕过

windows中1.txt和1.txt.两者是一个文件,所以就和空格绕过是一个思路

::$DATA绕过

利用Windows特性
在windows的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
例如:”phpinfo.php::$DATA”Windows会自动去掉末尾的::$DATA变成”phpinfo.php”

点空格点绕过

利用的就是程序员写代码时可能只会过滤一次特殊的关键词等,所以可以通过多次输入重复的关键词或者混着输入关键词来进行绕过

比如:

一次过滤
a.php->a.
a.pphphp->a.php 将中间的php过滤掉,还有一个php
但是当编写的是循环过滤的话,这个就会失效
a.pphphp->a.只要出现php就会过滤

双后缀名绕过

.pphphp

白名单绕过

%00截断——GET

原理:
www.xxx.com/qq.jpg
www.xxx.com/qq.php%00.jpg=>www.xxx.com/qq.php
%00是被服务器解码为0x00发挥了截断作用
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符
%00和0x00是由区别的;%00是URL中的,0x00是文件命名
%00需要PHP版本小于5.3.4,且打开的配置文件php-ini,将magic_quotes_gpc设置为Off

%00截断——POST

post不会解码%00->url编码

参考资料:https://www.yuque.com/samxara/swro13/tqdn5k

前言

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库

photo

SQL注入产生的原理

  1. 对用户输入的参数没有进行严格过滤(如过滤单双引号 尖括号等),就被带到数据库执行,造成了SQL注入
  2. 使用了字符串拼接的方式构造SQL语句

SQL注入的分类

  1. 从注入手法分类可以分为:联合查询注入、报错型注入、布尔型注入、延时注入、堆叠注入
  2. 从数据类型上可以分为:字符型(即输入的输入使用符号进行过滤)、数值型(即输入的输入未使用符号进行过滤)
  3. 从注入位置可以分类为:GET数据(提交数据方式为GET,大多存在地址栏)、POST数据(提交数据方式为POST,大多存在输入框中)、HTTP头部(提交数据方式为HTTP头部)、cookie数据(提交数据方式为cookie)

SQL注入的危害

分为两类:危害数据库里的数据、直接危害到网站的权限(需要满足条件)

  1. 数据库信息泄露
  2. 网页篡改:登陆后台后发布恶意内容
  3. 网站挂马 : 当拿到webshell时或者获取到服务器的权限以后,可将一些网页木马挂在服务器上,去攻击别人
  4. 私自添加系统账号
  5. 读写文件获取webshell

SQL注入

系统函数

information_schema.schemata 记录所有数据库名
information_schema.tables:记录所有表名信息的表
information_schema.columns:记录所有列名信息的表
schema_name 数据库名
table_name:表名
column_name:列名
table_schema:数据库名
system_user() 查看当前Mysqlsql登录用户名,同下
user() 查看当前MySQL登录的用户名
database() 查看当前使用MySQL数据库名
version() 查看当前MySQL版本
@@version_compile_os 查看操作系统
@@HOSTNAME 主机名称
@@datadir 数据库路径

常用函数

  1. floor() 向下取整
  2. rand() 返回一个大于0小于1的浮点数
  3. length(str) 返回字符串长度
  4. ascii(str) 返回字符串str的最左面字符的ASCII代码值,如果str是空字符串,返回0;如果str是NULL,返回NULL
  5. load_file() 读取本地文件 用法:select load_file(‘C:\phpstudy\www\sqli\Less-7\text.txt’);Mysql注入load_file常用路径
  6. into outfile 写文件 用法:select ‘mysql is good’ into outfile ‘test.txt’;
  7. if(condition,A,B)如果条件condition为true,则执行A,否则执行B
  8. chr(数字),ord(‘字母’) python中将字符或布尔类型转成ascii码

字符串拼接函数

  1. concat(str1,str2..)函数 没有分隔符串联多列结果
  2. concat_ws(separator,str1,str2,…) 含有分隔符串联多列结果
  3. group_concat(str1,str2,str3…) 用逗号,串联多行结果为一行
  4. order by关键字(select * from table_name order by 3)表示按第三列排序
  5. left(str,len) 对指定字符串从左边截取指定长度,正确返回1,错误返回0
  6. right(str,len)对指定字符串从右边截取指定长度
  7. substr(str,start,length)对于给定字符串,从start为开始截取length长度,如substr(“chinese”,3,2)=”in”.类似的还有substring()、mid()用法功能一致
  8. regexp函数 匹配正则

判断注入点

数字型
通过2-1与1的回显结果判断是否为数字型注入。有可能被()或者(())括起来

字符型
用单引号和双引号进行闭合。也有可能被(),(())包裹

photo

显错注入

Mysql在5.0以上版本加入了 information_schema 这个系统自带库 其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等

基本流程

  1. 判断字段数目order by 4…
  2. 判断显示位 union select 1,2,3,4…
  3. 查看当前数据库union select 1,2,database()
  4. 查表名union select 1,2,table_name from information_schema.tables where table_schema=database()
  5. 查列名union select 1,2,column_name from information_schema.columns where table_name=’表名’ and table_schema=database()
  6. 查询字段值union select 1,字段名,字段名 from 表名

盲注

基于布尔的盲注

这里主要使用mid(),substr(),left()这几个函数来截取字符串慢慢尝试

  1. 猜解当前数据库名称长度 and (length(database()))>1
  2. 通过http://127.0.0.1/sqli/Less-5/?id=1‘ and left((select database()),1)=’s’—+ 判断第一位是否是s,然后可以用bp逐步进行爆破处理
  3. 或者使用if来判断测试http://127.0.0.1/sqli/Less-5/?id=1‘ and ascii(substr((select database()),1,1))>156—+来通过二分法逐步判断
  4. 之后就是正常的注入流程,不断的猜表名、猜字段名和猜内容

基于时间的SQL盲注

一般来说,在页面没有任何回显和错误信息提示的时候,我们就会测试时间盲注的方法

主要通过if(length(database())=8,1,sleep())这样来判断语句是否注入成功
之后就是类似于布尔盲注的形式进行判定注入

例:/?id = 1’ and if((substr((select schema_name from information_schema.schmata limit 4,1),1,8)=’security’),1,sleep(5))—+

报错注入

floor()报错

and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

通过ExtractValue报错

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

通过UpdateXml报错

and updatexml(1,concat(0x5c,(select user()),0x5c),1)

其中concat函数是将其连接成一个字符串,因此不会符合XPath_string的格式,从而出现格式错误,爆出ERROR 1105 (HY000): XPATH syntax error: root@localhost

updatexml()函数

UPDATEXML(XML_document,XPath_string,new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string(Xpath格式的字符串)
第三参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值

通过NAME_CONST报错注入

and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

通过join报错注入

select from (select from mysql.user a join mysql.user b)c;

通过exp报错注入

and exp(~(select * from (select user()) a) );

通过GeometryCollection()报错注入

and GeometryCollection(()select *from(select user() )a)b;

通过ploygon()报错注入

and polygon (()select * from(select user())a)b;

通过multipoint()报错注入

and multipoint (()select * from(select user() )a)b;

通过multingestring()报错注入

and multlinestring (()select * from(select user() )a)b;

通过multpolygon()报错注入

and multpolygon (()select * from(select user() )a)b;

通过linestring()报错注入

and linestring (()select * from(select user() )a)b;

POST注入

头部POST注入

常用的请求头

  • HostHost
    Host请求报头域主要用于指定被请求资源的Internet主机和端口号。
    如:Host: localhost:8088

  • User-Agent
    User-Agent请求报头域允许客户端将它的操作系统、浏览器和其他属性告诉服务器。登录一些网站时,很多时候都可以见到显示我们的浏览器、系统信息,这些都是此头的作用。
    如:User-Agent: Mozilla/5.0

  • Referer
    Referer包含一个URL,代表当前访问URL的上一个URL,也就是说,用户是从什么地方来到本页面。
    如:Referer: http://192.168.33.1/sqli/Less-18/

  • Cookie
    Cookie是非常重要的请求头,它是一段文本,常用来表示请求者身份等。
    如:Cookie: username=admin; password=admin

  • Range
    Range可以请求实体的部分内容,多线程下载一定会用到此请求头。
    如:表示头500字节:Range: bytes=0~499
      表示第二个500字节:Range: bytes=500~999
      表示最后500字节:Range: bytes=-500
      表示500字节以后的范围:Range: bytes=500-

  • X-Forwarded-For
    X-Forwarded-For即XXF头,它代表请求端的IP,可以有多个,中间以逗号隔开。
    如:X-Forwarded-For: 8.8.8.8

  • Accept
    Accept请求报头域用于指定客户端接收哪些MIME类型的信息。
    如:Accept: text/html

  • Accept-Charset
    Accept-Charset请求报头域用于指定客户端接收的字符集。如果在请求消息中没有设置这个域,默认是任何字符集都可以接收。
    如: Accept-Charset: gb2312

二次注入

宽字节注入

DNS注入

通过sqli-labs进行学习
学习参考视频:https://www.bilibili.com/video/BV1e441127Rd

面向对象编程

类变量和类方法

类变量

类变量也叫静态变量,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量

  1. static(静态)变量是同一个类所有对象共享
  2. sataic类变量在类加载的时候就生成

定义语法:
访问修饰符 static 数据类型 变量名(推荐)
static 访问修饰符 数据类型 变量名

类变量与实例变量的区别

类变量是该类的所有对象共享的,而实例变量是每个对象独享的

类方法

类方法也叫静态方法
静态方法使用时可以直接使用

  1. 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:类方法中无this的参数,普通方法中隐含着this的参数
  2. 类方法可以通过类名调用,也可以通过对象名调用
  3. 普通方法和对象有关,需要通过对象名调用
  4. 类方法中不允许使用和对象有关的关键字,比如this和super。普通方法可以
  5. 静态方法中只能访问静态变量或静态方法
  6. 普通成员方法,既可以访问非静态成员,也可以访问静态成员
  7. 静态方法可以被继承,但不能被重写

理解main方法语法

  1. main方法是java虚拟机调用
  2. java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
  3. java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
  4. 该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数
  5. java 执行的程序 参数1 参数2 参数3
  6. 在main()方法中,可以直接调用main方法所在类的静态方法或静态属性
  7. 不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员

代码块

又称为初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用

基本语法
[修饰符]{
代码
};

代码块的好处

  1. 相当于另外一种形式的构造器,可以做初始化的操作
  2. 代码块调用顺序优先于构造器

细节讨论

  1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象,就执行
  2. 类什么时候被加载
    1. 创建对象实例时
    2. 创建子类对象实例,父类也会被加载
    3. 使用类的静态成员时
  3. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行
  4. 创建一个对象时,在一个类调用顺序时
    1. 调用静态代码块和静态属性初始化(两个优先级一样,按定义顺序调用)
    2. 调用普通代码块和普通属性的初始化(两个优先级一样,按定义顺序调用)
    3. 调用构造方法
  5. 构造器的最前面其实隐含了super()和调用普通代码块,在类加载时,就执行完毕
  6. 创建一个子类时,它们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序
    1. 父类的静态代码块和静态属性(优先级一样,按定义顺序)
    2. 子类的静态代码块和静态属性(优先级一样,按定义顺序)
    3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序)
    4. 父类的构造方法
    5. 子类的普通代码块和普通属性初始化
    6. 子类的构造方法
  7. 静态代码块只能调用静态成员,普通代码块可以调用任意成员

单例设计模式

单例模式就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

  1. 构造器私有化=》防止直接new
  2. 类的内部创建对象
  3. 向外暴露一个静态的公共方法

饿汉式VS懒汉式

  1. 二者最主要的区别在于创建对象的时机不同;饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建
  2. 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  3. 饿汉式存在浪费资源的可能,因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题
  4. javaSE标准类中,java.lang.Runtime就是单例模式

final关键字

final可以修饰类、属性、方法和局部变量

  1. 当不希望类被继承时,可以用final修饰
  2. 当不希望父类的某个方法被子类覆盖/重写时,可以用final关键字修饰
  3. 当不希望类的某个属性的值被修改,可以用final
  4. 当不希望某个局部变量被修改,可以使用final修饰

细节

  1. final修饰的属性又叫常量
  2. final修饰的属性在定义时,必须赋值,并且以后不能再修改,赋值可以在如下位置之一
    1. 定义时
    2. 在构造器中
    3. 在代码块中
  3. 如果final修饰的属性是静态的,则初始化的位置只能是定义时或在静态代码块,不能在构造器中赋值
  4. final类不能继承,但是可以实例化对象
  5. 如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承
  6. 一般来说,如果一个方法以及是final类了,就没必要再将方法修饰成final方法
  7. final不能修饰构造方法
  8. final和static往往搭配使用,效率更高,底层编译器做了优化处理
  9. 包装类(Integer,Double,Boolean等都是final),String也是final类

抽象类

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类

  1. 用abstract关键字来修饰一个类时,这个类就叫抽象类访问修饰符abstract 类名{}
  2. 用abstract关键字来修饰一个方法时,这个方法就是抽象方法 访问修饰符 abstract 返回类型 方法名(参数列表): //没有方法体
  3. 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()

抽象类细节

  1. 抽象类不能被实例化
  2. 抽象类不一定要包含abstract方法
  3. 一旦类包含了abstract方法,则这个类必须声明为abstract
  4. abstract只能修饰类和方法,不能修饰属性和其它的
  5. 抽象类可以有任意成员,比如:非抽象方法、构造器、静态属性等待
  6. 抽象方法不能有主体,即不能实现
  7. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类
  8. 抽象方法不能使用private、final和static来修饰,因为这些关键字都是和重写相违背的

抽象类-模板设计模式

接口

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来

在jdk8后,可以有默认实现方法,需要使用default关键字修饰,也可以有静态方法

接口细节

  1. 接口不能被实例化
  2. 接口中所有方法是public方法,接口中抽象方法,可以不同abstract修饰
  3. 一个普通类实现接口,就必须将该接口的所有方法都实现
  4. 抽象类实现接口,可以不用实现接口的方法
  5. 一个类同时可以实现多个接口
  6. 接口中的属性只能是final,而且是public static final 修饰符
  7. 接口中属性的访问形式:接口名.属性名
  8. 一个接口不能继承其他的类,但是可以继承多个别的接口
  9. 接口的修饰符只能是public和默认,这点和类的修饰符一样

接口和继承类

接口和继承解决的问题不同

继承的价值在于:解决代码的复用性和可维护性
接口的价值在于:设计好的各种规范,让其他类去实现这些方法

接口比继承更加灵活

接口在一定程度上实现代码解耦

接口多态

  1. 多态参数
  2. 多态数组
  3. 接口存在多态传递现象

内部类

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类,嵌套其他类的类称为外部类。内部类可以直接访问私有属性,并且可以体现类与类之间的包含关系

内部类的分类

定义在外部类局部位置上

  1. 局部内部类(有类名)
  2. 匿名内部类(没有类名,重点)

定义在外部类的成员位置上

  1. 成员内部类(没用static修饰)
  2. 静态内部类(使用static修饰)

局部内部类

局部内部类是定义在外部类的局部位置,比如方法中,并且有类名

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量不能使用修饰符。但是可以使用final修饰
  3. 作用域:仅仅在定义它的方法或代码块中
  4. 局部内部类—-访问—->外部类的成员【直接访问】
  5. 外部类—-访问—->局部内部类的成员【创建对象,再访问】
  6. 外部其他类—-不能访问—->局部内部类
  7. 如果外部类和局部内部类的成员方法重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问

匿名内部类

匿名内部类是定义在外部类的局部位置,比如方法中

成员内部类

定义在外部类的成员位置,没有static修饰

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 可以添加任意访问修饰符(pubic,protected,默认,private)
  3. 作用域和外部类的其他成员一样,为整个类体
  4. 成员内部类—-访问—->外部类【直接访问】
  5. 外部类—-访问—->内部类【创建对象,再访问】
  6. 外部其他类—-访问—->成员内部类
  7. 如果外部类和局部内部类的成员方法重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问

静态内部类

定义在外部类的成员位置,并且有static修饰

  1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
  2. 可以添加任意访问修饰符
  3. 作用域:为整个类体
  4. 静态内部类—-访问—->外部类【直接访问所有静态成员】
  5. 外部类—-访问—->静态内部类【创建对象,再访问】
  6. 外部其他类—->访问—->静态内部类
  7. 如果外部类和局部内部类的成员方法重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问

枚举和注释

自定义枚举

  1. 构造器私有化
  2. 本类内部创建一组对象
  3. 对外暴露对象
  4. 提供get方法,不提供set

枚举关键字

  1. 当我们使用enum关键字开发一个枚举类时,默认会继承Enum类,且不能继承其他类了
  2. 如果使用无参构造器 创建 枚举对象,则实参列表和小括号都可以省略
  3. 当有多个枚举对象时,使用,间隔,最后一个分号结尾
  4. 枚举对象必须放在枚举类的行首
  5. 枚举类和普通类一样,可以实现接口

Annotation元注解

  1. @Override:限定某个方法,是重写父类方法,该注解只能用于方法
  2. @Deprecated:用于表示某个程序元素(类,方法等)已过时
  3. @SuppressWarnings:抑制编译器警告
  4. @Target是修饰注解的注解

异常

  1. 异常分为两大类,运行时异常和编译时异常
  2. 运行时异常,编译器不要求强制处置的一次。一般是指编程时的逻辑错误
  3. 对于运行时异常,可以不做处理,因为很普遍,全处理可能会对程序的可读性和运行效率产生影响
  4. 编译时异常,是编译器要求必须处置的异常

运行时异常

  1. NullPointerException空指针异常。当应用程序试图在需要对象的地方使用null时,抛出该异常
  2. ArithmeticException数学运算异常。当出现异常的运算条件时,抛出此异常
  3. ArrayIndexOutOfBoundsException数组下标越界异常
  4. ClassCastException类型转换异常
  5. NumberFormatException数字格式不正确异常

编译异常

  1. SQLException。操作数据库时,查询表可能发生异常
  2. IOException 操作文件时,发生的异常
  3. FileNotFoundException 操作一个不存在的文件时,发生异常
  4. ClassNotFoundException 加载类,而该类不存在时,异常
  5. EOFException 操作文件,到文件末尾,发生异常
  6. ILLegalArguementException 参数异常

异常处理

  1. try-catch-finally。程序员自己处理
  2. throws。

try-catch处理异常

  1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入catch块
  2. 如果异常没有发生,则顺序执行try的代码块,不会进入到catch
  3. 如果希望不管是否发生异常,都执行某段代码,则使用finally
  4. 可以有多个catch,捕获不同的异常,要求父类异常在后,子类异常在前
  5. 可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉

try-catch-finally执行顺序

  1. 如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally,最后还需要执行finally里面的语句
  2. 如果出现异常,则try块中异常发生后,剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句

throws异常处理

  1. 对于编译异常,程序中必须处理,比如try-catch或者throws
  2. 对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
  3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
  4. 在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws

throw和throws的区别

  1. throws是异常处理的一种方式,在方法声明出,后面跟异常类型
  2. throw是手动生成异常对象的关键字,在方法体中,后面跟异常对象

常用类

包装类

包装类和基本数据类型的转换

  1. jdk5前手动装箱和拆箱方式,装箱;基本数据类型->包装类型,反之,拆箱
  2. jdk5以后的自动装箱和拆箱方式
  3. 自动装箱底层调用的是valueOf方法

String类

  1. String对象用于保存字符串,也就是一组字符序列
  2. 字符串常量对象时用双引号扩起的字符序列
  3. 字符串的字符使用Unicode字符编码,一个字符占两个字节
  4. String类较常用构造方法
  5. String是一个final类,代表不可变的字符序列
  6. 字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的

两种创建String对象的区别

方式一:直接赋值String s = “hsp”;
方式二:调用构造器 String s2 = new String(“hsp”);

  1. 方式一:先从常量池查看是否有”hsp”数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址
  2. 方式二:先在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有”hsp”,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址

photo

StringBuffer

代表可变的字符序列,可以对字符串内容进行增删

StringBuffer保存的是字符串变量,里面的值可以更改,每次更新实际上可以更新内容,不用更新地址

StringBuilder

一个可变的字符序列。不保证同步,用在字符串缓冲区被单个线程使用

Calendar

  1. Calendar是一个抽象类,构造器是private

集合

Collection接口

List

  1. List集合类中元素有序、且可重复
  2. List集合中的每个元素都有其对应的顺序索引,即支持索引
  3. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
ArrayList
  1. 可以加入null,并且多个
  2. 是由数组来实现数据存储的
  3. 基本等同于Vector,除了线程不安全
  4. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
  5. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍
LinkedList
  1. 实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全
  4. remove()默认删除第一个
Vector
  1. 底层也是对象数组
  2. Vector是线程同步的,即线程安全
  3. 如果是无参构造,则初始容量是10,每次按2倍扩容
  4. 如果是有参构造,则初始容量为指定大小,每次按2倍扩容

Set

  1. 无序(添加和取出的顺序不一致),没有索引
  2. 不允许重复元素,所以最多包含一个null
HashSet
  1. HashSet实现了Set接口
  2. 实际上是HashMap,HashMap底层是(数组+链表+红黑树)
  3. 可以存放null值,但是只能有一个null
  4. HashSet不保证元素是有序的,取决于hash后,再确定索引的结果
  5. 不能有重复元素/对象

HashSet添加元素底层实现

  1. 添加一个元素时,先得到hash值,会转成->索引值
  2. 找到存储数据表table,看这个索引位置是否已经存放的有元素
  3. 如果没有,直接加入。如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
  4. 在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64)就会进行树化

扩容机制

  1. 第一次添加时,table数组扩容到16,临界值是16*加载因子(loadFactor)是0.75=12
  2. 如果table数组使用到了临界值12,就会扩容到162=32,新的临界值就是320.75=24,依次类推
  3. 在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8)并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化,否则仍然采用数组扩容机制

去重机制
hashCode() + equals(),底层先通过存入对象,进行运算得到一个hash值,通过hash值得到对应的索引,如果发现table索引所在的位置,没有数据,就直接存放,如果有数据,就进行equals比较,不相同就加入,否则不加入

LinkedHashSet
  1. 是HashSet的子类
  2. 底层是LinkedHashMap,底层维护了一个数组+双向链表
  3. 根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,使得元素看起来是以插入顺序保存的
  4. 不允许添加重复元素
TreeSet

去重机制
如果你传入了一个Comparator匿名对象,就使用实现的compare去重,如果方法返回0,就认为是相同的,不添加。如果没有传入一个Comparator匿名对象,则以添加的对象实现的Comparable接口的compareTo去重

Map接口

  1. 与Collection并列存在,用于保存具有映射关系的数据
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复
  4. Map中的value可以重复
  5. Map中的key可以为null,value也可以为null,key为null只能有一个,value为null可以多个
  6. 常用String类作为Map的key

六大遍历方式

  1. containsKey
  2. keySet:获取所有的键
  3. entrySet:获取所有关系

HashMap

  1. 底层是数组+链表+红黑树
  2. 是以key-val对的方式来存储数据
  3. key不能重复,但是值可以重复,允许使用null键和null值
  4. 如果添加相同的key,则会覆盖原来的key-val,等同于修改
  5. 不保证映射的顺序,底层是以hash表的方式来存储的
  6. 没有实现同步,线程不安全

Hashtable

  1. 存放的元素是键值对:即K-V
  2. 键和值不能为null
  3. hashTable是线程安全的
  4. 底层有数组Hashtable$Entry[]初始化大小为11
  5. 临界值 threshold 8 = 11 * 0.75
  6. 扩容为2倍+1

Properties

  1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据
  2. 键和值不能为null

TreeMap

Collections工具类

  1. 是一个操作Set、List和Map等集合的工具类
  2. 提供了一系列静态的方法对集合元素进行排序、查询和修改等操作

泛型

  1. 传统的方法不能对加入到集合中的数据类型进行约束
  2. 传统的方法遍历的时候需要进行类型转换,如果集合中数据量较大,对效率有影响

使用泛型好处

  1. 编译时,检查添加元素的类型,提高了安全性
  2. 减少了类型转换的次数,提高效率
  3. 不再提示编译警告

泛型介绍

  1. 泛型又称参数化类型,解决数据类型的安全性问题
  2. 在类声明或实例化时只要指定好需要的具体的类型即可
  3. Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生异常。同时,代码更加简洁、健壮
  4. 可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型、
  5. 泛型不具备继承性

细节

  1. 普通成员可以使用泛型
  2. 使用泛型的数组,不能初始化
  3. 静态方法中不能使用类的泛型
  4. 泛型类的类型,是在创建对象时确定的
  5. 如果在创建对象时,没有指定对象,默认为Object

Java绘图技术

  1. Component类提供了两个和绘图相关最重要的方法
    1. paint(Graphics g)绘制组件的外观
    2. repaint()刷新组件的外观
  2. 当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件
  3. 以下情况paint()将会被调用
    1. 窗口最小化再最大化
    2. 窗口的大小发生变化
    3. repaint函数被调用

程序进程线程

Java常见基础知识

Java概述

JDK,JRE,JVM的关系

JDK(Java Development Kits Java开发工具包) = JRE(Java Runtime Environment Java运行环境)+ java开发工具
JRE = JVM(Java Virtual Machine Java虚拟机) + 核心类库

Java编写步骤

  1. 编写java的源代码
  2. javac 编译,得到对应的 .class 字节码文件
  3. java 运行,本质就是把 .class 加载到jvm 运行

Java编写7个规范

  1. 类,方法的注释,使用javadoc的方式,即文档注释
  2. 非javadoc注释,往往是对代码的说明(给程序的维护者),说明如何修改,注意事项
  3. 使用tab,整体将代码右移,使用shift+tab整体左移
  4. 运算符和 = 的两边,给空格,代码看上去清楚
  5. 源码文件使用 utf-8编码
  6. 行宽字符不要超过 80
  7. 代码编程风格有两种风格

变量

变量使用注意

  1. 变量表示内存中的一个存储区域
  2. 该区域有自己的名称和类型
  3. 变量必须先声明,后使用,即有顺序
  4. 该区域的数据/值可以在同一类型范围内不断变化
  5. 变量在同一个作用域内不能重名
  6. 变量=变量名+值+数据类型

程序中 +号使用

当左右两边都是数值型时,则做加法运算
当左右两边有一方为字符串,则做拼接运算
System.out.println(“100”+98);//10098
System.out.println(100+”98”);/10098

数据类型

整数类型
  1. Java各整数类型有固定的范围和字段长度,不受具体OS的影响,以保证java程序的可移植性
  2. Java的整型常量默认为int型,声明long型变量须后加“l”或“L”
  3. java程序中变量声明为int型,除非不足以表示大数,才使用long
  4. bit:计算机中的最小存储单位。byte:计算机中基本存储单元
浮点类型
  1. 与整数类型类似,Java浮点类型也有固定的范围和字段长度,不受具体OS的影响
  2. Java的浮点型常量默认为double型,声明float型常量,须后加“f”或“F”
  3. 浮点型常量两种表示形式
    1. 十进制数形式:如5.12 512.0f .512
    2. 科学计数法形式:5.12e2
  4. 通常情况下,应该使用double型,因为它比float型更精确
  5. 浮点数使用陷阱:2.7 和 8.1/3 比较
字符类型
  1. 字符常量是用单引号(‘’)括起来的单个字符
  2. Java中还允许使用转义字符’\’来将其后的字符转变为特殊字符型常量
  3. 在java中,char的本质是一个整数,在输出时,是unicode码对应的字符
  4. 可以直接给char赋一个整数,然后输出时,会按照对应的unicode字符输出
  5. char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码
布尔类型
  1. 布尔类型也叫boolean类型,boolean类型数据只允许取值true和false,无null
  2. boolean类型占1个字节
  3. boolean类型适用于逻辑运算,一般用于程序流程控制

自动类型转换

当java程序在进行赋值或运算时,精度小的类型自动转换为精度大的数据类型,为自动类型转换

基本数据类型转换
  1. 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算
  2. 当我们把精度大的数据类型赋值给精度小的数据类型时,就会报错,反之就会进行自动类型转换
  3. (byte,short)和char之间不会相互自动转换
  4. byte,short,char 他们三者可以计算,在计算时首先转换为int类型
  5. boolean不参与转换
  6. 自动提示原则:表达式结果的类型自动提升为 操作数中最大的类型
强制类型转换
  1. 当进行数据的大小从大—>小,就需要使用强制转换
  2. 强转符号只针对最近的操作数有效,往往会使用小括号提升优先级
  3. char类型可以保存int的常量值,但不能保存int的变量值,需要强转
  4. byte和short类型在进行运算时,当做int类型处理

运算符

算术运算符

取模%的本质 a%b = a - a / b * b

赋值运算符

关系运算符

逻辑运算符

&&与&的区别(||与|类似)

  1. &&短路与:如果第一个条件为false,则第二个条件不会判断,最终结果为false
  2. &逻辑与:不管第一个条是否为false,第二个条件都要判断
  3. 开发中,基本使用&&

位运算符

无符号右移 >> 算术右移 << 算术左移

三元运算符

基本语法:条件表达式?表达式1:表达式2

表达式1和表达式2要为可以赋给接收变量的类型(或可以自动转换)

进制

n进制转10进制

规则:从最低位开始,将每个位上的数据提取出来,乘以n的(位数-1)次方,然后求和

10进制转n进制

规则:将该数不断除以n,直到商为0为止,然后将每步得到的余数倒过来,就是对应的n进制

2进制转n进制

规则:从低位开始,将二进制数$sqrt(n)$位一组,转成对应的n进制数即可

n进制转2进制

规则:将n进制数每一位,转成对应点一个$sqrt(n)$位二进制数即可

原码反码补码

  1. 二进制的最高位是符号位:0表示正数,1表示负数
  2. 正数的原码,反码,补码都一样
  3. 负数的反码=它的原码符号位不变,其他位取反
  4. 负数的补码=它的反码+1,负数的反码=负数的补码-1
  5. 0的反码,补码都是0
  6. java没有无符号数,换言之,java中的数都是有符号的
  7. 在计算机运算的时候,都是以补码的方式来运算的
  8. 但我们看运算结果的时候,要看它的原码

控制结构

顺序结构

程序从上到下逐行地执行,中间没有任何判断和跳转

分支控制

if else 分支结构
switch 分支结构

注意case穿透,当没有break时,会跳到下一个执行语句,一直下去

  1. 表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以互相比较的类型,比如输入的是字符,而常量是int
  2. switch中表达式的返回值必须是:(byte,short,int,char,enum,String)
  3. case子句中的值必须是常量,而不能是变量
  4. default子句是可选的,当没有匹配的case时,执行default
  5. break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有写break,程序会顺序执行到switch结尾

循环控制

for循环控制

基本语法
for(循环变量初始化;循环条件;循环变量迭代){
循环操作(可以多条语句);
}

  1. 循环条件是返回一个布尔值的表达式
  2. for(;循环判断条件;)中的初始化和变量迭代可以写到其它地方,但是两边的分号不能省略
  3. 循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以由多条变量迭代语句,中间用逗号隔开
while循环控制

基本语法
while(循环条件){
循环体(语句);
循环变量迭代;
}

do-while循环控制

do{
循环体(语句);
循环变量迭代;
}while(循环条件)

break
1
2
3
4
5
6
7
8
9
10
lable1:
for(int j = 0;j < 4;j++){
lable2:
for(int i = 0;i < 10;i++){
if(i == 2){
break lable1;
}
System.out.println("i="+i);
}
}
  1. break 语句可以指定退出哪层
  2. lable1是标签,由程序员指定
  3. break后指定到哪个lable就退出到哪里
  4. 在实际的开发中,尽量不要使用标签
  5. 如果没有指定break,默认退出最近的循环体

数组、排序和查找

动态初始化

静态初始化

语法:数据类型 数组名[] = {元素值,元素值,,,}

数组使用注意事项和细节

  1. 数组是多个相同类型数据的组合,实现对这些数据的统一管理
  2. 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
  3. 数组创建后,如果没有赋值,有默认值int 0,short 0,byte 0,long 0,float 0.0,double 0.0,char \u0000,boolean false,String null
  4. 使用数组的步骤1.声明数组并开辟空间 2 给数组各个元素负债 3 使用数组
  5. 数组的下标是从0开始
  6. 数组下标必须是在指定范围内使用,否则报:下标越界异常
  7. 数组属引用类型,数组型数据是对象

数组赋值机制

  1. 基本数据类型赋值,这个值就是具体的数据,而且相互不影响
  2. 数组在默认情况下是引用传递,赋的值是地址

排序

内部排序

指将需要处理的所有数据都加载到内部存储器中进行排序

外部排序

数据量过大,无法全部加载到内存中,需要借助外部存储进行排序

二维数组

动态初始化

方式1 语法:类型[][] 数组名 = new 类型[大小][大小]

方式2
先声明:类型 数组名[][]
再定义数组名 = new 类型 [大小][大小]
赋值

面向对象

类与对象

Java内存的结构分析

  1. 栈:一般存放基本数据类型(局部变量)
  2. 堆:存放对象
  3. 方法区:常量池,类加载信息

形参列表

  1. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
  2. 参数类型可以为任意类型,包含基本类型或引用类型
  3. 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
  4. 方法定义时的参数统称为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致

方法调用细节

  1. 同一个类中的方法调用:直接调用即可
  2. 跨类中的方法A类调用B类方法:需要通过对象名调用
  3. 跨类的方法调用和方法的访问修饰符相关

递归

递归重要规则
  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响,比如n变量
  3. 如果方法中使用的是引用类型变量,就会共享该引用类型的数据
  4. 递归必须向退出递归的条件逼近,否则就是无限递归
  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕

方法重载

同一个类中,多个同名方法的存在,但要求形参列表不一致

重载的好处

  1. 减轻了起名的麻烦

注意事项

  1. 方法名必须相同
  2. 参数列表必须不同
  3. 返回类型无要求

可变参数

  1. 可变参数的实参可以为0个或任意多个
  2. 可变参数的实参可以为数组
  3. 可变参数的本质就是数组
  4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
  5. 一个形参列表中只能出现一个可变参数

构造器

构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化

特点
  1. 方法名和类名相同
  2. 没有返回值
  3. 在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化
注意事项
  1. 一个类可以定义多个不同的构造器,即构造器重载
  2. 构造器名和类名要相同
  3. 构造器没有返回值
  4. 构造器是完成对象的初始化,并不是创建对象
  5. 在创建对象时,系统自动的调用该类的构造方法
  6. 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造方法
  7. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下

对象创建流程

  1. 加载类信息,只会加载一次
  2. 在堆中分配空间(地址)
  3. 完成对象初始化(默认初始化,显式初始化,构造器初始化)
  4. 对象在堆中的地址,返回给p(p是对象名,也可理解为对象的引用)

this关键字

  1. this关键字可以用来访问本类的属性、方法、构造器
  2. this用于区分当前类的属性和局部布局
  3. 访问成员方法的语法:this.方法名
  4. 访问构造器语法:this(参数列表);只能在构造器中使用(即只能在构造器中访问另外一个构造器,必须放在第一条语句)
  5. this不能在类定义的外部使用,只能在类定义的方法中使用

三大作用

  1. 区分相同名字的类
  2. 当类很多时,可以很好的管理类
  3. 控制访问范围

命名规则:只能包含数字、字母、下划线、小圆点,不能用数字开头,不能是关键字或保留字

命名规范:com.公司名.项目名.业务模块名

访问修饰符

公开级别:用public修饰
受保护级别:用protected修饰,对子类和同一个包中的类公开
默认级别:没有修饰符号,向同一个包的类公开
私有级别:用private修饰,只有类本身可以访问,不对外公开
photo

  1. 修饰符可以用来修饰类中的属性,成员方法以及类
  2. 只有默认的和public才能修饰类,并且遵循上述访问权限的特点
  3. 成员方法的访问规则和属性完全一样

封装

封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作

封装的理解与好处
  1. 隐藏实现细节
  2. 可以对数据进行验证,保证安全合理
封装实现步骤
  1. 将属性进行私有化private 【不能直接修改属性】
  2. 提供一个公共的(public)set方法,用于对属性判断并赋值
  3. 提供一个公共的get方法,用于获取属性的值

继承

继承基本语法

class 子类 extends 父类{
}
子类就会自动拥有父类定义的属性和方法
父类又叫超类,基类
子类又叫派生类

细节
  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性不能在子类直接访问,要通过父类提供公共的方法去访问
  2. 子类必须调用父类的构造器,完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参的构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过
  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下
  5. super在使用时,需要放在构造器第一行
  6. super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  7. java所有类都是Object类的子类
  8. 父类构造器的调用不限于直接父类!将一直往上追溯到Object类
  9. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制
  10. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系

super关键字

  1. 访问父类的属性,但不能访问父类的private属性 super.属性名
  2. 访问父类的方法,不能访问父类的private方法 super.方法名(参数列表)
  3. 访问父类的构造器:super(参数列表);只能放在构造器的第一句
  4. 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问时一样的效果
  5. super的访问不限于直接父类,如果爷爷类和本类中有同名的的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则

方法重写/覆盖(override)

  1. 子类的方法的形参列表,方法名称,要和父类方法的参数,方法名称完全一样
  2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
  3. 子类方法不能缩小父类方法的访问权限

photo

多态

多态的具体实现
  1. 方法的多态。重写和重载就体现多态
  2. 对象的多态
    1. 一个对象的编译类型和运行类型可以不一致
    2. 编译类型在定义对象时,就确定了,不能改变
    3. 运行类型是可以改变的
    4. 编译类型看定义时 = 号 的左边,运行类型看 = 号的 右边
多态细节

多态的前提是:两个对象存在继承关系
多态的向上转型

  1. 本质:父类的引用指向了子类的对象
  2. 语法:父类类型 引用名 = new 子类类型();
  3. 特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员,不能调用子类中的特有成员;最终运行效果看子类的具体实现

多态的向下转型

  1. 语法:子类类型 引用名 = (子类类型)父类引用;
  2. 只能强转父类的引用,不能强转父类的对象
  3. 要求父类的引用必须指向的是当前目标类型的对象
  4. 可以调用子类类型中所有成员

属性没有重写之说,属性的值看编译类型
instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或xx类型的子类型

动态绑定机制
  1. 当调用对象方法时的时候,该方法会和对象的内存地址/运行类型绑定
  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
多态应用

多态数组:数组定义类型为父类类型,里面保存的实际元素类型为子类类型
多态参数:方法定义的形参类型为父类类型,实参类型运行子类类型

Object类详解

equals方法
  1. ==:既可以判断基本类型,又可以判断引用类型
  2. ==:如果判断基本类型,判断的是值是否相等
  3. ==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象
  4. equals:是Object类中的方法,只能判断引用类型
  5. equals默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等
hashCode方法
  1. 提高具有哈希结构的容器的效率
  2. 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的
  3. 两个引用,如果指向的是不同对象,则哈希值是不一样的
  4. 哈希值主要根据地址号来的!,不能完全将哈希值等价于地址
toString方法

默认返回:全类名+@+哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息

finalize方法
  1. 当对象被回收时,系统自动调用该对象的finalize方法,子类可以重写该方法,做一下释放资源的操作
  2. 什么时候回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁对象,在销毁该对象前,会先调用finalize方法
  3. 垃圾回收机制的调用,是由系统来决定,也可以通过System.gc()主动触发垃圾回收机制
断点调试

在断点调试过程中,是运行状态,是以对象的运行类型来执行的

重极限、连续、偏导数、全微分

重极限

求重极限常用方法

  1. 利用极限性质(四则运算法则,夹逼定理)
  2. 消去分母中极限为零的因子(有理化,等价无穷小代换)
  3. 利用无穷小量与有界变量之积的无穷小量

证明重极限不存在常用方法
沿两种不同路径极限不同(通常可取过($x_0,y_0$)的直线)

连续

若$\lim\limits_{\substack{x\rightarrow x_0 \\y\rightarrow y_0}}f(x,y)=f(x_0,y_0)$,则称$f(x,y)$在$(x_0,y_0)$处连续

性质

  1. 连续函数的和、差、积、商(分母不为零)及复合仍连续
  2. 基本初等函数在其定义域内连续;初等函数在其定义区域内连续
  3. 有界闭区域上连续函数的性质
    1. 有界性:若$f(x,y)$在有界闭区域D上连续,则$f(x,y)$在D上有界
    2. 最值性:若$f(x,y)$在有界闭区域D上连续,则$f(x,y)$在D上必有最大值和最小值
    3. 介值性:若$f(x,y)$在有界闭区域D上连续,则$f(x,y)$在D上可取到介于最小值与最大值之间的任何值

偏导数

全微分

以下四条等价

  1. $\Delta z=f(x_0+\Delta x,y_0+\Delta y)-f(x_0,y_0)=A\Delta x+B\Delta y+o(\rho)$
  2. $\lim\limits_{\substack{\Delta x\rightarrow0 \\ \Delta y\rightarrow0}}\frac{[f(x_0+\Delta x,y_0+\Delta y)-f(x_0,y_0)]-[A\Delta x+B\Delta y]}{\sqrt{(\Delta x)^2+(\Delta y)^2}}=0$
  3. $\Delta z=f(x,y)-f(x_0,y_0)=A(x-x_0)+B(y-y_0)+o(\rho)$
  4. $\lim\limits_{\substack{x\rightarrow x_0\\y\rightarrow y_0}}\frac{[f(x,y)-f(x_0,y_0)]-[A(x-x_0)+B(y-y_0)]}{\sqrt{(x-x_0)^2+(y-y_0)^2}}=0$

可微性判定

  1. 必要条件:$f’_x(x_0,y_0)$与$f’_y(x_0,y_0)$都存在
  2. 充分条件:$f’_x(x_0,y_0)$和$f’_y(x_0,y_0)$在$(x_0,y_0)$连续
  3. 用定义判定
    1. $f’_x(x_0,y_0)$和$f’_y(x_0,y_0)$是否都存在
    2. $\lim\limits_{\substack{\Delta x\rightarrow0 \\ \Delta y\rightarrow0}}\frac{[f(x_0+\Delta x,y_0+\Delta y)-f(x_0,y_0)]-[f’_x(x_0,y_0)\Delta x+f’_y(x_0,y_0)\Delta y]}{\sqrt{(\Delta x)^2+(\Delta y)^2}}$是否为零

连续、可导、可微的关系

photo

偏导数与全微分的计算

复合函数求导

设$u=u(x,y),v=v(x,y)$可导,$z=f(u,v)$在相应点有连续一阶偏导数,则

隐函数求导法

由一个方程所确定的隐函数
设$F(x,y,z)$有连续一阶偏导数,$F’_z\ne0,z=z(x,y)$由$F(x,y,z)=0$所确定
方法:

  1. 公式:$\frac{\delta z}{\delta x}=-\frac{F’_x}{F’_z},\frac{\delta z}{\delta y}=-\frac{F’_y}{F’_z}$
  2. 等式两边求导$F’_x+F’_z\frac{\delta z}{\delta x}=0,F’_y+F’_z\frac{\delta z}{\delta y}=0$
  3. 利用微分形式不变性:$F’_xdx+F’_ydy+F’_zdz=0$

注:
若$p(x,y)$和$Q(x,y)$有一阶连续偏导数,且$P(x,y)dx+Q(x,y)dy$是某一函数的全微分,则$\frac{\delta P}{\delta y}=\frac{\delta Q}{\delta x}$

极值与最值

无条件极值

极值的必要条件
设$z=f(x,y)$在点$(x_0,y_0)$存在偏导数,且$(x_0,y_0)$为$f(x,y)$的极值点,则$f’_x(x_0,y_0)=0,f’_y(x_0,y_0)=0$

极值的充分条件
设$z=f(x,y)$在点$P_0(x_0,y_0)$的某邻域内有二阶连续偏导数,又$f’_x(x_0,y_0),f’_y(x_0,y_0)=0$,记$A=f’’_{xx}(x_0,y_0),B=f’’_{xy}(x_0,y_0),C=f’’_{yy}(x_0,y_0)$
有下列结论

  1. 若$AC-B^2>0,$则$(x_0,y_0)$为f(x,y)的极值点
    1. A<0,则$(x_0,y_0)$为f(x,y)的极大值点
    2. A>0,则$(x_0,y_0)$为f(x,y)的极小值点
  2. 若$AC-B^2<0$,则$(x_0,y_0)$不为f(x,y)的极值点
  3. 若$AC-B^2=0$,则$(x_0,y_0)$可能为f(x,y)的极值点,也可能不为f(x,y)的极值点

求具有二阶连续偏导数二元函数$z=f(x,y)$极值的一般步骤为:
(1) 求出f(x,y)的驻点$P_1,\dotsb,P_k$
(2) 利用极值的充分条件判定驻点$P_i$是否为极值点
二元函数$z=f(x,y)$在偏导数不存在的点也可能取到极值(如$f(x,y)=\sqrt{x^2+y^2}$,而这种点是否取得极值一般用极值定义判定

条件极值及拉格朗日乘数法

求$z=f(x,y)$在条件$\varphi(x,y)=0$下的条件极值的一般方法:
(1) 构造拉格朗日函数$F(x,y,\lambda)=f(x,y)+\lambda\varphi(x,y)$;
(2) 将$F(x,y,\lambda)$分别对$x,y,\lambda$求偏导数,构造方程组

最大最小值

求连续函数$f(x,y)$在有界闭区域D上的最大最小值三部曲
(1) 求f(x,y)在D内部可能的极值点
(2) 求f(x,y)在D的边界上的最大最小值
(3) 比较

应用题

点到直线的距离公式:
直线为$Ax+By+C=0,A,B\ne0$,则直线外一点$(x_0,y_0)$到该直线最短的距离为$d=\frac{Ax_0+By_0+C}{\sqrt{A^2+B^2}}$

三角形面积公式:海伦公式
设三角形三边为x,y,z,周长为2p,则面积为$S=\sqrt{p(p-a)(p-b)(p-c)}$

二重积分的概念

二重积分的几何意义

二重积分$\iint_Df(x,y)d\sigma$是一个数。当$f(x,y)\ge0$时,其值等于以积分域D为底,以曲面$z=f(x,y)$为曲顶的曲顶柱体的体积

二重积分的性质

不等式性质

  1. 若在D上$f(x,y)\le g(x,y)$,则$\iint_Df(x,y)d\sigma\le\iint_Dg(x,y)d\sigma$
  2. 若$f(x,y)$在D上连续,则$mS\le\iint_Df(x,y)d\sigma\le MS$,其中m和M分别为$f(x,y)$在D上的最小值和最大值,S为积分域D的面积
  3. $|\iint_Df(x,y)d\sigma|\le\iint_D|f(x,y)|d\sigma$

积分中值定理

若$f(x,y)$在D上连续,则$\iint_Df(x,y)d\sigma=f(\xi,\eta)S$,其中$(\xi,\eta)\in D,S$为积分域D的面积

二重积分的计算

利用直角坐标计算

先y后x
若积分域D是X型区域,即积分域D可以用不等式$y_1(x)\le y\le y_2(x),a\le x\le b$来表示,则
photo

先x后y
若积分域D是Y型区域,即积分域D可以用不等式$x_1(y)\le x\le x_2(y),c\le y\le d$来表示,则
photo

利用极坐标计算

先r后$\theta$
若积分域D可以用不等式$r_1(\theta)\le r\le r_2(\theta),\alpha\le\theta\le\beta$,来表示,则
photo

利用对称性和奇偶性计算

(1) 若积分域D关于y轴对称,f(x,y)关于x有奇偶性,则:

(1) 若积分域D关于x轴对称,f(x,y)关于y有奇偶性,则:

利用变量对称性计算

二重积分$\iint_Df(x,y)d\sigma$的积分域D是点(x,y)的集合,记为$D_{(x,y)}$,类似一元定积分的值与积分变量用什么记号无关,则
photo

即把二重积分的被积函数f(x,y)及积分域$D_{(x,y)}$中的x和y对调,积分值不变

一阶微分方程的种类与解法

种类通解公式或解法
可分离变量的微分方程
$\frac{dy}{dx}=f(x,y)$,其中$f(x,y)=\varPhi_1(x)\varPhi_2(y)$
解法:
$\frac{dy}{dx}=f(x,y)\implies\frac{dy}{dx}=\varPhi_1(x)\varPhi_2(y)$
$\implies\frac{dy}{\varPhi_2(y)}=\varPhi_1(x)dx$
$\implies\int\frac{dy}{\varPhi_2(y)}=\int\varPhi_1(x)dx+C$
齐次微分方程
$\frac{dy}{dx}=f(x,y)$,其中$f(x,y)=\varPhi(\frac{y}{x})$
解法:
$\frac{dy}{dx}=f(x,y)\implies\frac{dy}{dx}=\varPhi(\frac{y}{x})$
$\xRightarrow{\frac{y}{x}=u} u+x\frac{du}{dx}=\varPhi(u)$
$\implies \int \frac{du}{\varPhi(u)-u}=\int \frac{dx}{x}+C$
一阶齐次线性微分方程
$\frac{dy}{dx}+P(x)y=0$
通解公式:
$y = Ce^{-\int P(x)dx}$(其中C为任意常数)
一阶非齐次线性微分方程
$\frac{dy}{dx}+P(x)y=Q(x)$
通解公式:
$y=[\int Q(x)e^{\int P(x)dx}dx+C]e^{-\int P(x)dx}$(其中C为任意常数)

可降阶的高阶微分方程及解法

种类解法
$y^{(n)}=f(x)$$y^{(n)}=f(x)$进行n次不定积分
$f(x,y’,y’’)=0$令$y’=p,y’’=\frac{dp}{dx},f(x,y’,y’’)=0$化为$f(x,p,\frac{dp}{dx})=0$
$f(y,y’,y’’)=0$$y’=p,y’’=\frac{dy}{dx}\cdot\frac{dp}{dy}=p\frac{dp}{dy},f(y,y’,y’’)=0$化为$f(y,p,p\frac{dp}{dy})=0$

高阶线性微分方程理论

n阶齐次线性微分方程
形如

n阶非齐次线性微分方程
形如

若$f(x)=f_1(x)+f_2(x)$,则(2)可分解为如下两个方程:

高阶线性微分方程解的结构

  1. 设$\varPhi_1(x),\varPhi_2(x),…,\varPhi_s(x)$为(1)的一组解,则$k_1\varPhi_1(x)+k_2\varPhi_2(x)+…+k_s\varPhi_s(x)$也为方程(1)的解
  2. 若$\varPhi_1(x),\varPhi_2(x)$分别为(1)、(2)的两个解,则$\varPhi_1(x)+\varPhi_2(x)$为(2)的一个解
  3. 若$\varPhi_1(x),\varPhi_2(x)$为(2)的两个解,则$\varPhi_1(x)-\varPhi_2(x)$为(1)的解
  4. 若$\varPhi_1(x),\varPhi_2(x)$分别为(2.1)及(2.2)的两个解,则$\varPhi_1(x)+\varPhi_2(x)$为(2)的解
  5. 若$\varPhi_1(x),\varPhi_2(x),…,\varPhi_s(x)$为(2)的一组解,则$k_1\varPhi_1(x)+k_2\varPhi_2(x)+…+k_s\varPhi_s(x)$为(2)的解的充分必要条件是$k_1+k_2+…+k_s=1$
  6. 若$\varPhi_1(x),\varPhi_2(x),…,\varPhi_s(x)$为(2)的一组解,则$k_1\varPhi_1(x)+k_2\varPhi_2(x)+…+k_s\varPhi_s(x)$为(1)的解的充分必要条件是$k_1+k_2+…+k_s=0$
  7. 设$\varPhi_1(x),\varPhi_2(x),…,\varPhi_n(x)$为(1)的n个线性无关解,则$k_1\varPhi_1(x)+k_2\varPhi_2(x)+…+k_n\varPhi_n(x)$为(1)的通解
  8. 若$\varPhi_1(x),\varPhi_2(x),…,\varPhi_n(x)$为(1)的n个线性无关解,$\varPhi_0(x)$为(2)的一个特解,则$k_1\varPhi_1(x)+k_2\varPhi_2(x)+…+k_n\varPhi_n(x)+\varPhi_0(x)$为(2)的通解

二阶常系数齐次线性微分方程及解法

方程形式$y’’+py’+qy=0$(其中p,q为常数)
特征方程$\lambda^2+p\lambda+q=0$
$\Delta=p^2-4q$的情况$y’’+py’+qy=0$的通解
$\Delta>0$$y=C_1e^{\lambda_1x}+C_2^{\lambda_2x}$($C_1,C_2$为任意常数)
$\Delta=0$$y=(C_1+C_2x)e^{\lambda_1x}$($C_1,C_2$为任意常数)
$\Delta<0$$\lambda_1=\alpha+i\beta,\lambda_2=\alpha-i\beta$
$y=e^{\alpha x}(C_1\cos\beta x+C_2\sin\beta x)$

三阶常系数齐次线性微分方程及解法

对$y’’’+py’’+qy’+ry=0$(其中p,q,r为常数),特征方程为

(1) 若特征值$\lambda_1,\lambda_2,\lambda_3$为实单根,则通解为$y=C_1e^{\lambda_1x}+C_2^{\lambda_2x}+C_3e^{\lambda_3x}$

(2) 若特征值$\lambda_1=\lambda_2\not=\lambda_3$为实根,则通解为$y=(C_1+C_2x)e^{\lambda_1x}+C_3e^{\lambda_3x}$

(3) 若特征值$\lambda_1=\lambda_2=\lambda_3$为实根,则通解为$y=(C_1+C_2x+C_3x^2)e^{\lambda_1x}$

(4) 若$\lambda_{1,2}=\alpha\pm i\beta,\lambda_3\in R$,则通解为$y=e^{\alpha x}(C_1\cos\beta x+C_2\sin\beta x))+C_3e^{\lambda_3x}$

二阶常系数非齐次线性微分方程的特解求法

类型一:$f(x)=e^{kx}P_n(x)$,其中$P_n(x)$为n次多项式

(1) 当$k\not ={\lambda_1}$且$k\not ={\lambda_2}$时,令特解$y_0(x)=(a_0+a_1x+…+a_nx^n)e^{kx}=Q(x)e^{kx}$

(2) 当$k={\lambda_1}$且$k\not ={\lambda_2}$时,令特解$y_0(x)=x(a_0+a_1x+…+a_nx^n)e^{kx}=xQ(x)e^{kx}$

(3) 当$k={\lambda_1}={\lambda_2}$时,令特解$y_0(x)=x^2(a_0+a_1x+…+a_nx^n)e^{kx}=x^2Q(x)e^{kx}$

类型二:$f(x)=e^{\alpha x}[P_m(x)cos\beta x+P_s(x)sin\beta x]$,其中$P_m,P_s(x)$分别为m及s次多项式

(1) 当$\alpha+i\beta$不是特征值时,令$y_0=e^{\alpha x}[Q_n^{(1)}(x)cos\beta x+Q_n^{2}(x)sin\beta x$,其中n=max{m,s},且$Q_n^{1}(x),Q_n^{2}(x)$为两个n次多项式

(2) 当$\alpha+i\beta$是特征值时,令$y_0=xe^{\alpha x}[Q_n^{(1)}(x)cos\beta x+Q_n^{2}(x)sin\beta x$,其中n=max{m,s},且$Q_n^{1}(x),Q_n^{2}(x)$为两个n次多项式

不定积分

两个基本概念

原函数
$F’(x)=f(x)$
不定积分
$\int f(x)dx=F(x)+C$

原函数的存在性

(1) 若$f(x)$在区间$I$上连续,则$f(x)$在区间$I$上必有原函数
(2) 若$f(x)$在区间$I$上有第一类间断点,则$f(x)$在区间$I$上没有原函数
(3) 若$f(x)$在区间$I$上只有震荡间断点,则$f(x)$在区间$I$上可能存在原函数(专指不定积分)

不定积分的性质

photo

基本积分公式

积分公式-1
积分公式-2

(23) $\int\tan^2xdx=\sec^2x-1+C$

(24) $\int\arcsin xdx=x\arcsin x+\sqrt{1-x^2}$

(25) $\int_{-\infty}^{+\infty}e^{-x^2}dx=\sqrt{\pi}$

(26) $\int_{-\infty}^{+\infty}e^{-\frac{x^2}{a}}dx=\sqrt{a}\int_{-\infty}^{+\infty}e^{-(\frac{x}{\sqrt{a}})^2}d\frac{x}{\sqrt{a}}=\sqrt{a\pi}$

三种主要积分法

第一类换元法(凑微分)

若$\int f(u)du=F(u)+C, and\varphi(x)$可导,则

第二类换元法

设函数$x=\varphi(t)$可导,且$\varphi’(t)\ne0$,又设$\int f(\varphi(t))\varphi’(t)dt=F(t)+C$,则$\int f(x)dx=\int f(\varphi(t))\varphi’(t)dt=F(\varphi^{-1}(x))+C$

三种常用的变量代换
(1) 被积函数中含有$\sqrt{a^2-x^2}$时,令$x=a\sin t,or x = a\cos t$
(2) 被积函数中含有$\sqrt{a^2-x^2}$时,令$x=a\tan t$
(3) 被积函数中含有$\sqrt{a^2-x^2}$时,令$x=a\sec t$

分部积分法

设$u(x),v(x)$有连续一阶导数,则$\int udv=uv-\int vdu$

三类常见可积函数积分

有理函数积分

三角有理式积分

(1) 一般方法(万能代换)
令$\tan\frac{x}{2}=t$
$\sin\alpha=\frac{2\tan\frac{\alpha}{2}}{1+\tan^2\frac{\alpha}{2}}、\cos\alpha=\frac{1-\tan^2\frac{\alpha}{2}}{1+\tan^2\frac{\alpha}{2}}、dx=\frac{2dt}{1+t^2}$

(2) 特殊方法(三角变形,换元,分部)

  1. 若$R(-\sin x,\cos x)=-R(\sin x,\cos x)$,则令$u=\cos x$,即凑$d\cos x$
  2. 若$R(\sin x,-\cos x)=-R(\sin x,\cos x)$,则令$u=\sin x$,即凑$d\sin x$
  3. 若$R(-\sin x,-\cos x)=R(\sin x,\cos x)$,则令$u=\tan x$,即凑$d\tan x$

简单无理函数积分

令$\sqrt[n]{\frac{ax+b}{cx+d}}=t$,将其化为有理函数积分进行计算

定积分

定积分的概念

定积分的几何意义

  1. 设$\int_a^bf(x)dx$存在,若在[a,b]上$f(x)\ge0$,则$\int_a^bf(x)dx$的值等于以曲线$y=f(x)$,$y=a,x=b$及x轴所围成的曲边梯形的面积
  2. 若在[a,b]上$f(x)\le0$,则$\int_a^bf(x)dx$的值等于以曲线$y=f(x),x=a,x=b$及x轴所围成的曲边梯形面积的负值
  3. 若在[a,b]上$f(x)$的值有正也有负,则$\int_a^bf(x)dx$在几何上表示$y=f(x),x=a,x=b$及x轴所围成的x轴上方图形的面积减去下方图形的面积所得之差

可积性

必要条件
若$\int_a^bf(x)dx$存在,则$f(x)$在[a,b]上有界

充分条件
(1) 若$f(x)$在[a,b]上连续,则$\int_a^bf(x)dx$必定存在
(2) 若$f(x)$在[a,b]上有界,且只有有限个间断点,则$\int_a^bf(x)dx$必定存在
(3) 若$f(x)$在[a,b]上只有有限个第一类间断点,则$\int_a^bf(x)dx$必定存在

f(x)在[a,b]上可积,则$\int_a^xf(t)dt$连续

定积分的计算

牛顿莱布尼茨公式
如果函数$F(x)$是连续函数$f(x)$在区间[a,b]上的一个原函数,则$\int_a^bf(x)dx=F(b)-F(a)$

换元积分法
设f(x)在区间[a,b]上连续,函数$x=\varphi(t)满足以下条件$:
(1) $\varphi(\alpha)=a,\varphi(\beta)=b$

(2) $\varphi(t)$在$\alpha,\beta$上具有连续导数,且其值域$R_\varphi=[a,b]$,则

分部积分法
设函数$u(x)、v(x)$在[a,b]上有连续一阶导数,则$\int_a^budv=uv|\overset{b}{a}-\int_a^bvdu$

利用奇偶性和周期性
(1) 设$f(x)$为[-a,a]上的连续函数(a>0),则

(2) 设$f(x)$是以T为周期的连续函数,则对任给数a,总有$\int_a^{a+T}f(x)dx=\int_0^Tf(x)dx$

利用公式
(1)
(2) $\int_0^\pi xf(\sin x)dx=\frac{\pi}{2}\int_0^\pi f(\sin x)dx$(其中$f(x)$连续)

变上限积分:$\int_a^xf(t)dt$

定理
若$f(x)$在[a,b]上连续,则$\int_a^xf(t)dt$在[a,b]上可导且$(\int_a^xf(t)dt)’=f(x)$

有关$F(x)=\int_a^xf(t)dt$在一点处的可导性的结论
| $f(x)$ | $F(x)=\int_a^xf(t)dt$ |
| —- | —- |
|连续|可导,且$F’(x_0)=f(x_0)$|
|可去间断|可导,且$F’(x_0)=\lim\limits_{x\rightarrow x_0}f(x)$|
|跳跃间断|连续但不可导,且$F_+’(x_0)=f(x_0^+),F_-‘(x_0)=f(x_0^-)$|

变上限求导的三个类型
(1) $(\int_{\varphi(x)}^{\psi(x)}f(t)dt)’= f(\psi(x))\psi’(x)-f(\varphi(x))\varphi’(x)$

(2) $(\int_a^bf(x,t)dt)’=\int_a^b\frac{\vartheta f(x,t)}{\vartheta x}dt$

连续性
设$f(x)$在[a,b]上可积,则$\int_a^xf(x)dt$在[a,b]上连续

奇偶性
(1) 若$f(x)$为奇函数,则$\int_a^xf(t)dt$为偶函数

(2) 若$f(x)$为偶函数,则$\int_0^xf(t)dt$为奇函数

定积分的性质

不等式
(1) 若$f(x)\le g(x),x\in[a,b]$,则$\int_a^bf(x)dx\le\int_a^bg(x)dx$

(2) 若$f(x)$在[a,b]上连续,则$m(b-a)\le\int_a^bf(x)dx\le M(b-a)$,其中m,M分别为$f(x)$在[a,b]上的最小值与最大值

(3) $|\int_a^bf(x)dx|\le\int_a^b|f(x)|dx$

积分中值定理
(1) 若$f(x)$在[a,b]上连续,则$\int_a^bf(x)dx=f(\xi)(b-a),a<\xi<b$

(2) 若$f(x),g(x)$在[a,b]上连续,且$g(x)$不变号,则$\int_a^bf(x)g(x)dx=f(\xi)\int_a^bg(x)dx,a\le\xi\le b$

积分不等式

柯西积分不等式:$(\int_a^bf(x)g(x)dx)^2\le\int_a^bf^2(x)dx\int_a^bg^2(x)dx$

反常积分

无穷区间上的反常积分

定义 设$f(x)$为$(-\infty,+\infty)$上的连续函数,如果反常积分$\int_{-\infty}^0f(x)dx$和$\int_0^{+\infty}f(x)dx$都收敛,则称反常积分$\int_{-\infty}^{+\infty}f(x)dx$收敛,且$\int_{-\infty}^{+\infty}f(x)dx=\int_{-\infty}^0f(x)dx+\int_0^{+\infty}f(x)dx$
如果$\int_{-\infty}^0f(x)dx$与$\int_0^{+\infty}f(x)dx$之一发散,则称$\int_{-\infty}^{+\infty}f(x)dx$发散

定理1(比较判别法) 设$f(x),g(x)$在$[a,+\infty)$上连续,且$0\le f(x)\le g(x)$,且

(1) 当$\int_a^{+\infty}g(x)dx$收敛时,$\int_a^{+\infty}f(x)dx$收敛

(2) 当$\int_a^{+\infty}f(x)dx$发散时,$\int_a^{+\infty}g(x)dx$发散

定理2(比较法的极限形式) 设$f(x),g(x)$在$[a,+\infty)$上非负连续,且$\lim\limits_{x\rightarrow+\infty}\frac{f(x)}{g(x)}=\lambda$(有限或无穷),则

(1) 当$\lambda\ne0$时,$\int_a^{+\infty}f(x)dx$与$\int_a^{+\infty}g(x)dx$同敛散

(2) 当$\lambda=0$时,若$\int_a^{+\infty}g(x)dx$收敛,则$\int_a^{+\infty}f(x)dx$也收敛

(3) 当$\lambda=+\infty$时,若$\int_a^{+\infty}g(x)dx$发散,则$\int_a^{+\infty}f(x)dx$也发散

常用结论:

无界函数的反常积分

定理1(比较判别法 设$f(x),g(x)$在$(a,b]$上连续,且$0\le f(x)\le g(x),x=a$为$f(x)$和$g(x)$的瑕点,则
(1) 当$\int_a^bg(x)dx$收敛时,$\int_a^bf(x)dx$收敛
(2) 当$\int_a^bf(x)dx$发散时,$\int_a^bg(x)dx$发散

定理2(比较法的极限形式 设$f(x),g(x)$在$(a,b]$上非负连续,且$\lim\limits_{x\rightarrow a^+}\frac{f(x)}{g(x)}=\lambda$(有限或无穷),则
(1) 当$\lambda\ne0$时,$\int_a^{b}f(x)dx$与$\int_a^{b}g(x)dx$同敛散
(2) 当$\lambda=0$时,若$\int_a^bg(x)dx$收敛,则$\int_a^bf(x)dx$也收敛
(3) 当$\lambda=+\infty$时,若$\int_a^bg(x)dx$发散,则$\int_a^bf(x)dx$也发散

常用结论:

定积分应用

几何应用

平面图形的面积
设有平面域D,则该平面域D的面积为$\iint_D1d\sigma$
(1) 若平面域D由曲线$y=f(x),y=g(x)(f(x)\ge g(x)),x=a,x=b(a<b)$所围成,则
photo

(2) 若平面域D由曲线$r=r(\theta),\theta=\alpha,\theta=\beta(\alpha<\beta)$所围成,则面积为
photo

空间体的体积
(1) 旋转体的体积
平面域D绕直线L:ax+by+c=0(该直线不穿过区域D)旋转所得旋转体体积记为V
photo

特别的,若区域D由曲线$y=f(x)(f(x)\ge0$和直线$x=a,x=b(0\le a\le b)$及x轴所围成,则
(1) 区域D绕x轴旋转$(r(x,y)=y)$一周所得旋转体的体积为

(2) 区域D绕y轴旋转$(r(x,y)=x)$一周所得旋转体的体积为

(2) 横截面面积的体积
photo

曲线弧长
(1) 设曲线段C由直角坐标方程$y=f(x)(a\le x\le b)$给出,其中$y(x)$在[a,b]上有一阶连续导数,则该曲线段的弧长为

(2) 设曲线段C由参数方程$\begin{cases}
x=x(t),\\
y=y(t),
\end{cases}(a\le t\le \beta)$给出,其中$x(t),y(t)$在$[\alpha,\beta]$上有一阶连续导数,则该曲线段的弧长为

(3) 设曲线段C由极坐标方程$r=r(\theta)(\alpha\le\theta\beta)$给出,其中$r(\theta)$在$[\alpha,\beta]$上有一阶连续导数,则该曲线段的弧长为

(4) 旋转体侧面积
曲线$y=f(x)(f(x)\ge0)$和直线$x=a,x=b(0\le a\le b)$及x轴所围成区域绕x轴旋转所得旋转体的侧面积是

特殊图形

星形线
星形线
直角坐标方程:$x^{\frac{2}{3}}+y^{\frac{2}{3}}=a^{\frac{2}{3}}$
极坐标方程:$x=a\cos^3t,y=a\sin^3t$
围成面积$A=4\int_0^aydx$
弧长$L=4\int_0^a\sqrt{1+y’^2}dx$
绕x轴体积$V=2\pi\int_a^a y^2dx$
旋转体横截面积$2*2\pi\int_0^ay\sqrt{1+y’^2}dx$

摆线
摆线
极坐标方程:$x=a(t-\sin t),y=a(1-\cos t)$

心形线
心形线
极坐标方程:$r=a(1+\cos\theta)$

双纽线
双纽线
直角坐标方程:$(x^2+y^2)^2=a^2(x^2-y^2)$
极坐标方程:$r^2=a^2\cos2\theta$
旋转体侧面积:$2\int_0^\frac{\pi}{4}2\pi*r\sin\theta\sqrt{r^2+r’^2(\theta)}d\theta$

物理应用

  1. 压力
    1. 水的压力F=水的压强P x 装水的容器的底面积S(F=pghS)
  2. 变力做功
  3. 引力

质心计算公式$r_\sigma=\frac{\sum_im_ir_i}{M}$和$r_\sigma=\frac{\int^b_ax\rho(x)dx}{\int^b_a\rho(x)dx}$