Java那些事儿

00. 引言

入行已经近两年,其中好多知识点只是囫囵吞枣,看过多次仍旧不能理解设计理念,还是从小处入手,整理笔记,多看,多想,多思考,耐心且谦虚,徐徐图之,才能进阶。

01. Java语言

1.1 Java概述

1.1.1 简介

Java是Sun Microsystems于1995年推出的高级编程语言

1991 年Sun公司的James Gosling等人开始开发名称为 Oak (橡树)的语言。希望用于控制嵌入在有线电视交换盒、PDA等的微处理器

1994年将Oak语言更名为Java

Java 既安全、可移植,又可跨平台,而且人们发现它能够解决Internet 上的大型应用问题

2009年,sun被oracle收购。
java-Oka

1.1.2 技术平台

JavaSE:Java Platform,Standard Edition (标准版

Java中最通行的版本,包含Java核心类和GUI(图形用户界面)类

适合于开发桌面系统和低端商务应用系统。

JavaEE:Java Platform,Enterprise Edition (企业版

包含开发基于Web的应用程序的类和接口,如Servlet、JSP、JDBC、EJB、JMS以及Enterprise JavaBeans等

为企业提供电子商务构架及Web服务的解决方案,领域涉及:办公自动化OA、客户关系管理CRM、企业资源计划ERP、营销管理、财务管理……等等,几乎你能够想到的所有应用。

JavaME:Java Platform, Micro Edition (微型版

对传呼机、移动电话、掌上电脑、汽车导航系统、医疗设备、信息家电或其他无线设备等产品提供优化的运行时环境

是移动商务最佳的应用典范

1.1.3 程序特点

简单易用、完全面向对象

平台无关性、可扩展性强

可移植性高、支持分布式编程

半编译半解释型

健壮、安全可靠并性能优异

支持多线程开发技术

支持动态开发

1.1.4 开发步骤

java语言: 人—> 电脑

(1)把要求用java语言写出来(编写源程序,如Hello.java)

(2)编译源程序(编译后的文件称为字节码文件,如Hello.class)

(3)运行

在这里插入图片描述

互联网应用程序:

​ 1.面向对象

​ 2.跨平台

1.1.5 平台无关性

Java最重要的特性就是它的平台无关性,编译后的Java程序可直接在不同的平台上运行而不用重新编译

一次编译到处运行

一次编译到处运行

JVM(Java Virtual Machine)是一个想象中的机器,在实际的计算机上通过软件模拟实现,有自己虚拟的硬件(处理器、堆栈、寄存器等)及其相应的指令系统。

1.2 Java环境搭建

运行java程序,需要下载jdk, jdk是程序员开发Java程序的Java开发工具包。

JDK包括JRE(java runtime envirnment),Java运行环境、一堆Java工具和Java基础的类库

官方网站下载:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

版本:jdk1.0, …, jdk6.0, jdk7.0, jdk8.0

演示:jdk8.0安装

环境搭建步骤:

1.2.1 下载安装jdk

jdk: java development kit, java开发工具包,包含java的开发环境和运行环境。

jre:java runtime envirnment,java运行时环境,包含java的运行环境。

jvm:java virtual machine, java虚拟机,包含java运行的必备环境。

jdk的目录结构
bin可执行文件
lib类库文件
include本地方法的文件
db数据库的文件
jre运行环境的文件
src.zipapi的源代码

1.2.2 配置环境变量

​ JAVA_HOME:配置java安装的根路径

​ CLASS_PATH:配置java安装的根路径/lib

​ path: 调用可执行命令,配置java安装的根路径/bin

1.2.3 测试

​ javac:编译命令

​ java:执行命令 java -jar

1.3 第一个java程序

1.3.1 基本结构

​ 外层是一个类,内层是main方法。

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

1.3.2 用Eclipse做java开发

创建java project

新建类,写源代码

保存

运行

1.3.3 注释

​ JAVA中的注释是用来帮助使用该程序的人理解源程序的含义和作用。其内容不会被Java编译器编译。

单行注释:单行注释以“ // ” 开始,以行末结束

多行注释:以“ /* ” 开始,以 “ */ ” 结束 ,注意:不能嵌套

文档注释:用于完成帮助文档的生成。

1.4 Java中的关键字

关键字是由Java语言保留的、Java的开发和运行平台认识、并能正确处理的一些单词。关键字是在Java语言和Java的开发和运行平台之间的约定,只要按照这个约定使用了某个关键字,Java的开发和运行平台就能够识别它,并正确的处理它。

提示:

Java中的关键字也是随着版本的变化不断变动中的,不是一成不变的。

Java中所有的关键字都是小写。

Java中的goto、const是保留字,而非关键字。

表示类的关键字是class。

java关键字列表

类、接口和枚举类型声明class、extends、implements、interface、enum
包引入和包声明import、package
基本数据类型boolean、byte、char、double、float、int、long、short
某些数据类型的可选值true、false、null
流程控制break、return 、continue、switch 、case 、default、do、while、for、if、else
异常处理try、catch、finally、throw、throws
修饰符abstract、final、native、private、protected、public、static、synchronized、transient、volatile
操作符instanceof
创建对象new
引用this、super
方法返回类型void
保留关键字const、goto

程序需要注意的问题:

程序的文件名必须与主类名一致。

一个文件中可以包含多个类,但是只有一个类前面可以有public修饰,这个就是主类。

java区分大小写。(大小写敏感的语言)

main方法是程序的入口,有且只能有一个。

每条语句都必须以分号结尾。

除了要输出的内容和注释外,其他的都是英文状态下的。

对于一些成对的符号,如:{},(),[],’’,"",必须成对出现。

为了便于阅读,代码要添加适当的注释和缩进。

域名倒写 文件名:**com.zph.myjava **

1.5 包(package)

1.5.1 创建包的语句

package 包名;

注意:该句必须位于文件的第一句。

包名:一般由小写字母和数字、小圆点组成,不能圆点开头或结尾。

注意:包与文件夹的对应关系。

1.5.2 导入包

语法:import 包名.类名;

如果要导入该包下的所有类:import 包名.*;

1.6 变量

内存存数据,需要知道:

1.存哪了?

2.分配多大的空间? 15,15000,一篇文章,张三

变量就是存储数据的一个基本单元,在程序运行期间,其值可以发生改变。

1.6.1 变量命名规则

在Java语言中, 标识符是给类、变量和方法等取的名称。

标识符的命名规则:

由字母、数字、下划线、$符号组成,但不能以数字开头

不能是关键字和保留字

区分大小写

标识符的长度没有限制。

中文的变量和字符也是合法的,但不推荐使用。

1.6.2 变量命名规范

简短且能清楚地表明变量的作用,(见名知意)

通常第一个单词的首字母小写,其后单词的首字母大写。例如:myScore

问题:检查下面这些是否是合法的变量名

principa $lastname zip code 123rate discount%

cost_price marks-3 city City int

1.6.3 变量的使用步骤

1.声明:数据类型 变量名

2.赋值

3.使用

  int age;
  age=20;
  System.out.println(age);

2. 数据类型、运算符、条件结构

2.1 类型划分

类型划分

2.1.1 整数类型

类型名字节(比特位)范围
byte1(8bit)-128~127
short2(16bit)-32768~32767
int4(32bit)-2147483648~2147483647
long8(64bit)-9223372036854775808~9223372036854775807

注意:

  1. long类型的数据后面要加L或l

  2. java中可以表示十进制、八进制(以0开头)、十六进制(以0x开头)的数字。

  3. n位二进制数的取值范围是:-2(n-1)至2(n-1)-1.其中“xy”是表示“x的y次幂”byte是8位二进制,所以是-27至2^7-1也就是-128至127

二进制计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。 0 1 01 11 100 101 110 111
八进制Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。一些编程语言中常常以数字0开始表明该数字是八进制。八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中。
十进制满十进一,满二十进二,以此类推……2.按权展开,第一位权为100,第二位101……以此类推,第N位10^(N-1),该数的数值等于每位位的数值*该位对应的权值之和。
十六进制英文名称:Hexadecimal 是计算机中数据的一种表示方法。同我们日常生活中的表示法不一样。它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9;A-F对应10-15;N进制的数可以用0~(N-1)的数表示,超过9的用字母A-F。

2.1.2 浮点型

​ 浮点类型用于表示有小数部分的数值。在Java中有两种浮点类型,如下表所示:

类型名字节(比特位)范围
float4(32bit)-3.4E38 ~ 3.4E38
double8(64bit)-1.7E308 ~1.7E308

注意:

JAVA中浮点型常量默认为double型,也可以在数字后面加d或D;要声明一个常量为标准的float型,则需在数字后面加f或F。 Double d=1.23e3; d=1230.0

Double.MAX_VALUE是double的最大值;

浮点型的数字都是近似值。

2.1.3 char类型

2个字节,只能表示一个字符(可以是英文字母、数字、符号、汉字)

字符常量是用单引号括起来的单个字符,如: char c = ‘A’;

char 的默认值是码位为 0 的Unicode编码的字符 。 字符型数据对应了int的正半轴,是int类型的一个子集

2.1.4 String类型

在java中用String类型来表示字符串,是引用数据类型,不是基本数据类型。

字符串常量用双引号括起来,如String str = “hello”;

2.1.5 boolean类型

boolean类型适合于逻辑运算,只允许取值true或false,不可以使用0或非0的整数替代true和false。(1字节)

2.2 转义序列符

    \n, \t, \”,\’,\\

2.3 基本数据类型转换

(1)自动类型转换

​ 两种类型兼容,目标类型>源类型:

​ Byte–>short–>int–>long–>float–>double

​ char–>int

(2)强制类型转换

​ 两种类型兼容,目标类型<源类型

​ 格式:(目标类型)(表达式);

2.3 运算符

2.3.1 赋值运算符

=,+=,-=,*=,/=,%=

​ =:表示将右边的值赋值给左边的变量。

2.3.2 算术运算符:

​ 二元(双目)运算符:+, -, *, /, %

​ 一元(单目)运算符:++, –

注意:

​ 对于/:如果两个操作数都是整数,则做整除运算。

​ %:表示两个数相除的余数。

​ ++:表示自增1;- - :表示自减1。

​ ++如果做前缀,先增1,再取值;如果做后缀,先取值,后增1。

2.3.3 关系运算符

>,   <,  >=,  <=,  ==,  !=

​ 比较的结果是布尔类型的。

2.3.4 逻辑运算符

&&, ||, !

条件1 && 条件2:并且,只有两个条件都是真,结果才为真。

条件1 || 条件2:或者,只有当两个条件都是假,结果才是假。

! 条件:一元运算符,表示否定。

注意:&&,||用于逻辑运算时,如果第一个表达式能决定整个式子的结果,那么第二个表达式就不计算。

2.3.5 位运算符(了解)

​ &:按位与

​ |:按位或

​ ^:异或,如果两个数字相同,则结果是0,否则是1

​ <<:左移位

​ >>:右移位

​ >>>:无符号右移位

注意:&,|也可以用于逻辑运算,但是他们会每个表达式都计算。

2.3.6 条件运算符:?:

语法:

​ 条件 ? 表达式1 : 表达式2;

表示如果条件成立,结果是表达式1,否则,结果是表达式2。

案例:**int max=a>b ? a : b ; //**最大值

l 闰年的判定规则为:能被 4 整除但不能被100 整除的年份,或能被 400 整除的年份。

2.3.7 运算符的优先级

高—>低:

()

一元运算符:++, --, !

算术:*,/,%

+,-

关系:>, <, >=, <=

​ ==, !=

逻辑:&&

​ ||

赋值:=, +=, -=, *=, /=, %=

3. 条件结构

3.1 if条件

3.1.1 一种情况

if(条件){
     操作

3.1.2 两种情况

if(条件){
    操作
}else{
    操作
}

3.1.3 多重if语句

if(条件1){
  操作1
}else if(条件2){
  操作2
}else{
  其他操作
}

else if块可以有多块。

else块可以没有。

3.2 switch语句

语法:

switch(变量){
    case1:
        语句块1;
        break;
    case2:
        语句块2;
        break;.
    default:
        其他语句;
        break;
}

switch需要注意的问题

  1. switch能针对的类型:整型(long除外)、char、String、枚举

  2. 只能等值判断。

  3. switch要判断的变量和case后面的值类型必须一致。

  4. break:结束switch语句。

  5. case块、default块顺序可以互换

  6. case后面的值不允许重复。

  7. case中如果没有break会继续向下执行。

3.3 多重if和switch比较

相同点:都能表示多种情况

区别:多重if能表示所有的多种情况;switch只能针对整型(long除外)、char、String做等 值判断

3.4 While

场景:

循环结构:在满足某种条件的情况下,重复的做某件事情

打印输出5个hello。

开始:个数=0

条件:个数<5个

事情:输出一个hello

​ 个数增加1

3.4.1 while循环

语法:

 while(循环的条件){
      做的事情
}

特点:先判断,后执行

注意:

1) 执行之前,一定要检查循环能否退出。

2) 循环的次数要正确:如果要循环n次,i从0开始,i<n;i从1开始,i<=n

做题的步骤:

1) 分析循环的条件和操作

2) 套用语法

3) 检查是否是死循环

3.4.2 do-while循环

语法:

do{
   做的事情
}while(条件);

特点:先执行,后判断

如果循环条件一开始就不满足:

​ while循环一次也不执行。

​ do-while循环至少会执行一次。

3.5 for循环

3.5.1 语法

for(表达式1; 表达式2;表达式3){
     操作
 }

for(初始化A;循环的条件B;循环变量的改变C){
    操作D
}

注意:三个表达式都可以省略,但是分号不能省略。

3.5.2 执行顺序

​ A, B, D, C, B, D, C ……, B, D, C, B

特点:先判断,后执行。(与while相同)

适合于循环次数确定的循环。

3.6 流程控制语句

(1)break:能用于switch语句和循环语句。

​ 用于循环,表示结束整个循环。

(2)continue:只能用于循环语句。

​ 表示结束本次循环,继续执行下一次。

​ 对于for循环,continue跳转到表达式3继续执行。

​ 对于while、do-while循环,跳到条件继续执行。

4. 数组

4.1 概念

​ 数组,是一个特殊的变量,能存储相同数据类型的一组数;通过整型下标访问元素,下标从0开始编号;数组是引用数据类型的。

4.2 使用步骤

4.2.1 声明

数据类型 [ ] 数组名; [ ]表示数组

​ int[] arr;

​ 也可以:int arr[];

4.2.2 分配空间

数组名=new 数据类型[长度];

​ arr=new int[3];

​ 长度只能是整型数据,可以是常量、变量,但必须有确定的值。

​ 1,2可以合并:int[] arr2 = new int[3];

4.2.3 给元素赋值

(1) 单个元素给赋值

 arr[0]=11;

(2) 循环给赋值

for(i=0;i<arr.length;i++){
        System.out.println("请输入第"+(i+1)+"个元素的值:");
        arr[i]=in.nextInt();
 }

(3) 边声明边赋值

int[] a = {11,12,13,14,15,16};
int[] b = new int[]{21,22,23,24};
int[] c; c=new int[]{31,32,33};

(4) 用已知数组给赋值:

​ 注意:此时这两个数组指向同一个数据区域,一个改变,另外一个也跟着改变。

(5)使用

动态的求数组的长度:数据名.length

System.out.println("数组的元素个数:"+arr.length);
for(i=0;i<arr.length;i++){
    System.out.println(arr[i]);
}

// 当下标越界时,会抛出以下异常:(数组下标越界异常)

java.lang.ArrayIndexOutOfBoundsException

4.3 for each循环

​ 用变量依次代替数组中的每一个元素

 for(变量类型 变量:数组或集合){ 
      操作    
 }   
int[] arr = new int[]{11,12,13,14};
for(in n:arr){
   System.out.println(n);
}

注意:数组是引用数据类型的,可以不赋初始值,系统会自动给赋值(本类型的零值,数字: 0,引用:null)

4.4 数组的应用

​ for(变量:数组集合){ 操作 }

​4.4.1 循环的输入、输出

​4.4.2 求总和、平均值

float sum = 0;
System.out.println("5个学生的成绩如下:");
for(i=0;i<scores.length;i++){
	System.out.print(scores[i]+"  ");
	sum+=scores[i];
}
avg=sum/scores.length;

​4.4.3 求最大、最小值

max=arr[0];
w1=0;
min=arr[0];
w2=0;
for(i=1;i<arr.length;i++){
    if(max<arr[i]){
        max=arr[i];
        w1=i;
    }
    if(min>arr[i]){
        min=arr[i];
        w2=i;
    }
}

​4.4.4 排序

Arrays.sort(dog, new Comparator(){…}

Arrays.sort(数组名); // 只能升序排序

选择排序

冒泡排序

int i, j, t;
		for(i=0;i<arr.length-1;i++){
			for(j=0;j<arr.length-1-i;j++){
				if(arr[j]>arr[j+1]){
					t=arr[j];
					arr[j]=arr[j+1];
					arr[j+1]=t;
				}
			}
		}
//总共比arr.length-1轮,每一轮两两交换,交换arr.length-1-i次,其中i为交换的轮数,j为每一轮交换的次数    

4.4.5 查找

		System.out.println("请输入你要查找的数字:");
		int zh=in.nextInt();
		int w=-1;
		for(i=0;i<arr.length;i++){
			if(zh==arr[i]){
				w=i;
				break;
			}
		} 

4.5 二维数组

java中没有多维数组的概念,把二维数组看作是“数组的数组”。

        //声明
		int[][] arr=new int[2][3];  行列
		int i,j;
         //赋值
        //循环输入
		for(i=0;i<2;i++){
			for(j=0;j<3;j++){
				System.out.println("请输入第"+(i+1)+"个学生的第"+(j+1)+"门课的成绩:");
				arr[i][j]=in.nextInt();
			}
		}
    //循环输出
	for(i=0;i<2;i++){   
			sum=0;
			for(j=0;j<3;j++){
				System.out.print(arr[i][j]+"\t");     //不换行
				sum+=arr[i][j];
			}
				System.out.println(sum+"\t"+(sum/3)); //换行
	}

5. 方法

​ 方法就是完成特定功能的代码块,在很多语言里面都有函数的定义,函数在Java中被称为方法。

5.1 基本格式

修饰符(public)返回值类型 方法名(参数类型 参数名1,参数类型 参数名2) {
       函数体(完成该功能的语
       return 返回值;
}

5.2 参数

形参:形式参数,函数定义(方法声明)时,格式:类型 参数名1, 类型 参数名2,……

​ 案例:public static void printRect(int row,int col){ }

实参:实际参数,方法调用时,可以是常量、变量,但是必须要有确定的值。

​ 注意:实参的类型、个数、顺序必须与形参一致

​ 案例:printRect3(4,6);

功能:数据传送(实参 形参)。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。

5.3 返回值类型

5.3.1 没有返回值

返回值类型写void。

调用:方法名( );

    add1(12,3);
    public static void add1(int a,int b){
    		int c;
    		c=a+b;
    		System.out.println("结果:"+c);
    }

5.3.2 有返回值

5.3.2 有返回值

返回值类型与return后面的值的类型一致。

方法体中必须要有”return值;”语句。

调用:变量=方法名( );

int s1=add2(11,2);
public static int add2(int a,int b){
		int c;
		c=a+b;
		return c;
}

return:表示该方法调用结束,返回主调方法。

​ 注意:return语句最多返回一个值。

​ “return;”表示不返回任何值,可以用在无返回值的方法中。

​ “return值;”只能用于有返回值的方法。

5.4 递归调用

迭代的是人,递归的是神。

​ –L. Peter Deutsch

n 汉诺塔

​ 当函数直接或者间接调用自己时,则发生了递归。

int s2=jiecheng(5);
System.out.println("s2="+s2);
public static int jiecheng(int n){
		int s;
		if(n==1){
			s=1;
		}else{
			s=n*jiecheng(n-1);
		}
		return s;
}

5.5 可变(不定)参数

​ 适用于参数个数不确定,类型确定的情况。

​ 当成数组使用,可以接收0或多个值。??

调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中一数组的形式访问可变参数。???

​ 注意:一个方法最多只能由一个可变参数,且必须在参数列表的最后一个。

add(1,2);

add2(1,2,3,4,5);

add3("hello",9,8);

public static void add(int a,int b)

public static void add2(int...arr)

public static void add3(String s,int...arr)

public static void add3(String s,int...arr)   {       …….     }  

5.6 方法重载

​ 方法重载(overloading)是让类以统一的方式处理不同类型数据的一种手段。

​ 调用方法时通过传递给它们的不同个数类型的参数来决定具体使用哪个方法,这就是多态性。

在同一个类中,存在多个方法名相同,参数列表不相同(参数的类型、个数或顺序至少有一项是不同)的方法,这些方法就构成了方法重载。

与返回值类型、访问修饰符无关。

    add(1,2);
	add(1.2f,2.4f);
	add(1,2,3);
	add(12,4.5f);
	add(1.2f,34);
    public static void add(int a,int b)
    public static int add(int a)
	public static void add(int a,int b,int d)
	public static void add(float a,float b)
	public static void add(int a,float b)
	public static void add(float b, int a)

6 面向对象

​ 思想:基础语法、应用

6.1 概述

6.1.1 类

描述的是一类事物。是具有相同或相似性质的对象的抽象。

​ 抽象的概念。

​ 可以看作是模版

​ 可以看作是对象的类型(引用数据类型)

​ 不占用空间

6.1.2 对象

描述的是一个具体的事物。

​ 具体的个体

​ 可以看作是一个具体的实例

​ 可以看作是类类型的一个变量

​ 占用空间

6.1.3 对象怎么描述

​ 属性:对象所具有的各种特征。

方法:对象所有的行为或功能。

​ eg: 狗:属性:品种、颜色、年龄、性别、体重。。。

​ 方法:站立,玩,……

6.1.4 类也包含属性和方法

6.1.5 面向对象的主要特征

封装、继承、多态

​ 封装:

方法:代码块。

类:属性和方法

6.1.6 面向对象的优点

(1)便于模拟现实世界

(2)隐藏细节

(3)可以实现代码重用

6.2 命名规范

(1)见名知意

(2)包名一般由小写字母组成

(3)类名首字母大写

(4)变量名、方法名一般小写;常量名大写

6.3 变量的作用域

​ 由变量声明的位置决定。分成两种:

(1)成员变量:直接声明在类中,该类的所有方法都可以访问。

(2)局部变量:声明在某个方法或语句块内,只有该方法或语句块可以使用。

注意:如果局部变量和成员变量重名,局部变量会隐藏成员变量,要想在该方法中使用成员变量,必须使用关键字this。

6.4 方法调用

(1)如果两个方法在同一类,直接写名字调用。

   float java,html,db,s;
	//方法
	public float sum(){
		float s;
		s=java+html+db;
		return s;
	}
	public float avg(){
		float a;
		a=sum()/3;
		return a;
	}

(2)如果两个方法不在同一个类,必须先创建该方法所在类的对象,然后对象名.方法名()

public class A{
    public void a(){
            B b=new B();  //创建b方法所在类B的对象
            b.b();      //对象名.方法
    }
}

6.5 属性封装

​ 类:属性和方法

​ 方法:代码块。

​ 属性:隐藏

6.5.1 基本格式


public class A{.
	String name;
    public int abc(String s, float f, int a){.
		return 12;
    }
}

main()调用:
	A a1=new A();
	A a2=new A();
	int s1 = a1.abc(“hello”, 1.2f, 9);
	String name = ”aaa”;
	float f=2.4f;
	int s2=a2.abc(name, f, s1);

6.5.2 访问修饰符

修饰符范围
public公有的,该项目中的所有类都可以访问。
protected保护的,只有本包内的类和它的子类可以访问。//类的内部可访问;同一个包下的不管是否有继承关系均可访问;不同包下只有有继承关系的才可访问
default默认的:只有本包内的类可以访问。//类的内部可访问;同一个包下不管是否有继承关系均可访问;不同包下不管有没有继承关系都不能访问。
private私有的,只有本类可以访问

6.5.3 属性的封装

(1) 封装步骤

将属性私有化

给属性添加公有的get和set方法

如果需要对属性值的范围进行限制,在set方法中进行。

(2)关键字this:表示本实例的,本对象

区分局部变量和(实例)成员变量

​ 当局部变量和成员变量重名时,用**this.**调用的是成员变量,不用this.调用的是局部变量。

调用本类其他的构造方法,格式:this(实参);

​ 注意:该句必须位于方法的第一句。

(3)属性封装的优点:

​ 安全,控制更灵活(读、写分开)

6.6 构造方法

(1) 作用:负责对象成员的初始化(给属性赋值)

(2) 语法:与类同名、没有返回值类型的方法。

(3) 调用:创建对象时,用new关键字调用。

创建对象:

 类名 对象名 = new 构造方法();
//Teacher t1 = new Teacher();

注意:

1) 如果类中没有自定义构造方法,系统会自动添加一个无参的构造方法;如果有自定义的构造方法,系统就不添加了。

2) 构造方法可以重载

6.7 方法重载

​ 在同一个类,方法名相同,参数列表不同的多个方法。

构造方法重载:

public Teacher(String name,int age){
		this.name=name;
		this.setAge(age);
		System.out.println("2个参数的构造被调用!");
	}
	public Teacher(String name){
		this.name=name;
		this.age=30;
		this(name,30);
		System.out.println("1个参数的构造被调用!");
	}
	public Teacher(){
		this("无名",30);
		System.out.println("0个 参数的构造被调用!");
	}

6.8 static静态的

6.8.1 修饰属性

静态属性:又称为类属性,用static修饰的属性。

​ 属于类,在内存中只分配一份内存,该类的所有对象共享该内存。

​ 调用:类名.属性

static int count=0; System.out.println(“开始人数:”+Student.count);

实例属性:没有static修饰的属性。

​ 属于每个对象,在内存中每个对象都有自己的内存空间

​ 调用:对象名.属性

​ String name; System.out.println(s1.name);

6.8.2 修饰方法

静态方法:可以直接访问静态成员(属性和方法),不能直接访问实例成员。

​ 如果要访问实例成员,必须先创建对象,然后用对象名.去调用。

​ public static void showCount(); Student.showCount();

实例方法:可以直接访问实例成员、静态成员。

​ public void introduce(); s1.introduce();

// main方法单独放置:public static void main(String[] args)

6.8.3 静态&&实例代码块

静态代码块实 例 代 码 块
static{ …… }{ …. }
类加载 时调用,只调用这一次每创建一个对象,都调用一次。(构造方法之前调用)直接放在类中,用{}括起来的代码:做初始化工作。

7 继承

7.1 概念

7.1.1 类与类之间的关系

依赖关系:use-a

组合关系:has-a

继承关系:is-a

继承关系中,会有父类和子类。父类具有通用的特征,子类可以继承到父类的通用特征,然后还可以添加自己特有的特征。

7.1.2 父类、子类

父类:superclass, 超类,基类 basedclass

子类:subclass, 派生类或导出类 derivedclass

7.2 继承

(1)继承的关键字:extends

(2)继承的优点:可以有效的实现代码重用。

7.3 注意问题

(1)子类是否能继承父类中所有的成员?

访问修饰符:所有的都可以继承,但是否能直接访问由访问修饰符控制。

(2)构造方法:

创建子类对象时,默认调用父类无参的构造方法。

如果父类没有无参的构造方法,或需要调用父类带参的构造方法:必须用super关键字显示调用。

public Person(String name,char sex,int age){
    this.name=name;
    this.sex=sex;
    this.age=age;
}

public Student(int num,String name,char sex,int age){
    super(name,sex,age); //必须位于第一句
    this.num=num;
}

调用格式:super(实参); 注意:必须位于第一句。

(3)单继承

一个类只能有一个父类。(java继承的单根性)

(4)所有类的根类:java.lang.Object

(5)子类可以重写父类的方法。

7.4 方法重写

overriding 又叫方法覆盖

public void teach(){
     System.out.println("回顾");
     System.out.println("讲解");
     System.out.println("总结");
}
@Override
public void teach() {
    // TODO Auto-generated method stub
    System.out.println(this.getName()+"老师正在讲"+this.getLesson()+":");
    System.out.println("打开eclipse...");
    super.teach();
}

子类中可以存在与父类中,方法名、参数列表、返回值类型完全一致的方法,这时,就成子类重写了父类的方法。要求:访问范围不能缩小。

7.5 父类的super

作用:

(1)调用父类的构造方法,格式:super(实参);

注意:必须位于第一句。

public DTeacher(String name){
        super(name,"DB");
 }

(2)方法重写后,调用父类被隐藏的方法,格式:super.方法名();

8 多态

8.1 概念

具有表现多种形态的能力。

​ 对于同一个实现接口,接收的对象不同结果可能不同。

​ (同一个方法,实现结果可能不同)

8.2 多态的表现形式

方法重载:静态多态、编译时多态,在程序编译期间,由参数匹配。

方法重写:动态多态、运行时多态,在程序运行期间,由对象的实际类型决定调用哪个类中的方法。

8.3 方法重写实现的多态

1) 要有继承关系

2) 方法重写

3) 要用父类的引用去调用重写的方法。

9 关键字及接口

9.1 final

可以修饰属性、方法、类

属性:表示常量,其值在运行期间不可改变。

方法:该方法不允许重写,可以继承。

类:不能被继承。

备注

常量必须赋初始值,可以在以下任意一个地方:声明处、构造方法里。

常量的优点:增强程序的可读性、可维护性。

常量一般用大写字母表示

9.2 abstract

可以修饰方法、类、接口(不用也行,用上了也没区别)

抽象方法:用abstract修饰的,没有方法体的方法。必须通过子类进行重写,然后使用。

抽象类:用abstract修饰的类。

备注

包含抽象方法的类必须是抽象类。

抽象类不能实例化。(new 抽象类(); 这是错误的)

9.3 interface

类似usb接口:统一的标准、规范。

语法:

public interface 接口名{

//数据,全部都是常量
[public] [final] 数据类型 常量名=;        [.]<---------表示可以省略的内容
 …
//方法,全部都是抽象方法
[public] [abstract] 返回值类型 方法名(参数列表);}

注意:

接口的访问修饰符可以是public或默认的。

数据成员全都是常量,public, final可以省略,省略以后系统会自动添加。

方法全部都是抽象方法,public, abstract可以省略,省略以后系统会自动添加。

接口不能实例化

接口中也没有构造方法

自动类型转换:类–>所实现的接口

类实现接口:implements

一个类可以实现多个接口。

一个接口也可以有父接口,子接口,

接口的继承:extends,一个接口可以有多个父接口。

接口作用:

可以看作类与类之间的“协议”。(规范,标准),实现多继承(作为类的补充)

9.4 抽象类和接口区别

(abstract class , interface)

共同点:都可以包含抽象方法,都不能实例化。

区别:

抽象类接口
属性:可以是常量、变量只能是常量
方法:可以有抽象方法、具体方法只能有抽象方法
成员可以有私有成员全部是public
一个类只能继承自一个父类一个类可以实现多个接口

9.5 instanceof

检查对象的实际类型

10 异常Exception

10.1 异常概念

在程序运行期间,发生的不正常的事件,会导致程序中断。

父类:Throwable 子类:Error、Exception

10.1.1 Exception

(异常、例外),因编程原因,操作不当等,一般性的问题,表示可恢复的例外,这是可捕捉到的

比如:输入类型不合法、除数为0、要打开的文件的不存在

1) 检查异常(checked Exception):必须处理。checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。

2) 运行异常(runtime Exception):不强迫处理。我们可以不处理。当出现这样的异常时,总是由虚拟机接管。(比如:InputMismatchException, ArithmeticException, IndexOutofBoundsException, NullPointerException, ……)

10.1.2 Error

比较严重的错误,JVM内部资源耗尽、偶然因素导致的,不允许捕获无法处理。

Error类代表了编译和系统的错误,不允许捕获

表示由JVM所侦测到的无法预期的错误,由于这是属于JVM层次的严重错误,导致JVM无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显示错误信息。

10.2 异常的处理

五个关键字

try{
	//有可能会抛异常的代码以及会受影响的代码
}catch(异常类型 参数名){
	//对异常的处理
}finally{
	//finally里面的代码无论任何情况都会执行
}
e.printStackTrace();  //输出错误的堆栈信息

每个try后面可以带多个catch块,这些块的顺序:先子类,后父类。

注意:这些catch块只能执行一个,不能同时执行多个。

保证程序不中断,运行至最后。

10.3 异常处理流程

try{
    A;
    B; //有可能会抛异常的代码
    C;
}catch(异常类型1 参数名){
	D
} catch(异常类型2 参数名){
	E
}finally{
	F
}
	G

​ try…catch执行的3种情况:

1) 正常情况:A, B, C, F, G

2) 有异常但能捕获(异常类型1可以捕获):A, B, D, F, G

3) 有异常但不能捕获:A, B, F, 中断

10.4 throw, throws

throw:手动抛出异常,用于程序员自定义的异常

格式: throw 异常对象;

 throw new Exception(“错误原因!”);

throws:声明方法有可能抛出异常。

格式: throws 异常类型

public void sub(int a, int b)throws Exception{.
}

10.5 自定义异常类

自己创建的异常类,必须直接或间接继承自Exception。

11. String

这是一个类,位于java.lang包

因为java.lang包默认已导入,所以不需要显式导入。

String类,表示字符串,特点:不可变对象(耗内存、效率低)

11.1 创建对象

 String s1 = ”hello”;
 String s2 = new String(“hello”);
 in.next():输入时,遇到空白符(空格、tab键、回车)就结束了
 in.nextLine():输入时,只有遇到回车才结束,所以可以输入空格、tab键

11.2 常用方法

对象名.方法名

[长度]字符的个数 length()
int len=name.length();
[比较]
1)区分大小写的比较
		 boolean b=name.equals(name2);
2)忽略大小写的比较
		if(name.equalsIgnoreCase(name2)){
3)全部转换为大写或小写,然后再比较
		if(name.toLowerCase().equals(name2.toLowerCase()))
[连接]
1)	+
String s3=name+"和"+name2+"是好朋友。";
2) concat()
		String s4=name.concat(",你好!");
[分割] split()
			String[]s1=sports.split("-");
提取单个字符
注意:字符串从0开始编号
		char ch=s.charAt(1);
[提取子串]
1)提取从指定位置(包含)开始到结束的所有字符
		String s1=s.substring(3);
2)提取从开始位置(包含)到结束位置(不包含)之间的字符
		String s2=s.substring(3, 6);
[搜索]
1)	搜索字符或字符串第一次出现的位置,返回下标
注意:如果找不到,返回-1
			int w1=s.indexOf("abc");
2)第一个参数表示要搜索的字符串,第二个参数表示开始的位置
			int w2=s.indexOf("abc", 4);
3)返回指定字符在此字符串中最后一次出现处的索引
			int s5=s.lastIndexOf("6");
4)返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
			int w3=s.lastIndexOf("abc", 6);

11.3 正则表达式

11.3.1 概念

正则表达式Regular Expression

表达式,如2+5,能完成对字符串的一些判断【非逻辑性】

​ 正则表达式定义了字符串的模式。

​ 正则表达式可以用来搜索、编辑或处理文本。

​ 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。

11.3.2 作用

验证字符串是否合法

String的matches()方法

基本的正则表达式符号:

(API:字符类、预定义字符类、Greedy数量词)

11.3.3 使用​

String pwd="ab_1238";
String reg="\\w{6,}";
boolean b=pwd.matches(reg);
System.out.println("b="+b);

11.3.4 附录

​ [ ]表示一位

(1)字符类

[abc]abc(简单类)
[^abc]任何字符,除了 abc(否定)
[a-zA-Z]azAZ,两头的字母包括在内(范围)
[a-d[m-p]]admp[a-dm-p](并集)
[a-z&&[def]]def(交集)
[a-z&&[^bc]]az,除了 bc[ad-z](减去)
[a-z&&[^m-p]]az,而非 mp[a-lq-z](减去)​

(2)预定义字符类

.任何字符(与行结束符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字: [^0-9]
\s空白字符:[ \t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9] 用户名常用
\W非单词字符:[^\w]

(3)Greedy 数量词

X?X,一次或一次也没有 (0,1)
X*X,零次或多次 (所有的)
X+X,一次或多次 (1,多次)
X{n}X,恰好n次
X{n,}X,至少n次
X{n,m}X,至少n次,但是不超过m次。

(4)注意

1)\d使用时应该是:“\d”,\需要使用转义序列符。

2).代表任意字符,如:".",如果要判断是否包含小数点,应该用"[.]"

判断是否有中文:String reg = “[\u4e00-\u9fa5]+”;//是否包含一个或多个中文

​ 验证“\”,正则表达式要写“\\”:

​ String s1=“a\b”;

​ String reg="[ac]\\[ac]";

boolean b=s1.matches(reg);

​ 或的表示:(19|20)表示19或20

11.4 StringBuilder(Buffer)

这两个类也表示字符串。特点:可变对象

 创建对象:	
		StringBuilder sb=new StringBuilder(“hello”); 标准的类的声明方式
		sb=”abc”; //这个是错误,不能使用“=”进行赋值。
 常用方法:

    1.连接,追加
        StringBuilder中的连接不能使用+进行连接运算,连接使用append()方法
		StringBuilder sb2=sb.append(",ABC");
     2.删除
  		1)删除指定位置的字符
         sb.deleteCharAt(5);
        2)删除从开始位置(包含)到结束位置(不包含)之间的字符
         sb.delete(2, 5);
     3.插入
        在指定位置插入指定的内容
        sb.insert(2, "llo,");
     4.替换
        将从开始位置(包含)到结束位置(不包含)之间的字符替换为指定的内容
        sb.replace(2, 6, "今天有雪");
     5.反转
        sb.reverse();
     6.转换成String类型
        String s1=sb.toString();
        System.out.println(s1);

// 注意:StringBuilder和StringBuffer不能使用equals()进行字符串内容的比较(),如果要比较,必须转换成String类型再比较。

11.5 String, StringBuilder, StringBuffer的区别

相同点:String,StringBuilder,StringBuffer都不能产生子类(都由final修饰)

分类原理应用
String不可变对象,如果要对已创建好的对象进行修改,都必须重新分配内存。(耗内存、效率低)应用灵活String s1=”hello”;String s2=new String(“hello”);可以使用+做连接,=做赋值
StringBuilder可变对象。线程不同步StringBuilder sb=new StringBuilder(“hello”);不能使用+,=
StringBuffer可变对象。线程同步(安全,效率低)StringBuffer sb=new StringBuffer (“hello”);不能使用+,=

11.6 String s=new String( “xyz” );

创建了几个对象?

第一个对象是字符串常量"xyz"
第二个对象是new String(“xyz”)的时候产生的,在heap(堆区)中分配内存给这个对象,只不过这个对象的内容是指向字符串常量"xyz"
另外还有一个引用s,指向第二个对象。这是一个变量,在stack(栈区)中分配内存。

11.7 public String intern();

返回字符串对象的规范化表示形式。

它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

返回: 一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池。

12 Object

​ 位于java.lang包,是所有类的根类

object

12.1 toString()

​ 默认返回:包名.类名@hashcode

​ 如果要直接输出对象,需要重写此方法

12.2 hashCode()

​ 返回此对象的hash码

​ 由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的)

一般情况:对象不同,hashCode也不同

有可能:对象不同,hashCode相同

(尽量不重写)

12.3 equals()

比较两个对象的内容是否相同。

默认:只有两个引用都是非空的,并且指向同一个对象时,才返回true。

需要自定义比较规则时,需要重写此方法。

12.4 clone()

创建并返回此对象的一个副本

类要实现Cloneable接口,并重写clone()方法。

12.5 finalize()

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。垃圾回收时,调用此方法

12.6 其他的

getClass():反射时用;

wait(), notify(), notifyAll():多线程时用。

13 包装类

13.1 数据类型

​ 基本数据类型:byte, short, int, long, float, double, char, boolean

​ 包装类:Byte, Short, Integer, Long, Float, Double, Character, Boolean

13.2 基本类型–>包装类类型​

int a=123;
Integer i1=new Integer(a); //标准
Integer i2=a;    //简化         

13.3 包装类类型->基本类型

Integer i3=new Integer(24);
int b=i3.intValue();   //标准
int c=i3;             //简化

13.4 基本数据类型->包装类类型->引用数据类型

 //int,float,double --> String
int a=123;
Integer i1=a;
String s1=i1.toString();

//更简单的
String s2=a+"";

13.5 引用数据类型->包装类类型->基本数据类型​

//String --> int, float, double
String s3="56";
int b=Integer.parseInt(s3);
float f=Float.parseFloat(s3);
double d=Double.parseDouble(s3);

14 日期和时间

14.1 Date

位于java.util包,类 Date 表示特定的瞬间,精确到毫秒。

14.1.1 Date->String

		//创建对象
		Date d1=new Date();
		//规定日期格式sdf
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh-mm-ss E");
		//使用方法并保存到字符串中
		String today=sdf.format(d1);
		//输出
		System.out.println("today="+today);

14.1.2 String-> Date

	String s1="2018年01月04日 11-13-45 星期四";
	try {
	    SimpleDateFormat sdf1=new SimpleDateFormat("yyyy年MM月dd日hh-mm-ss E");
		Date d2 = sdf1.parse(s1);
		System.out.println("d2="+d2);
	} catch (ParseException e) {
	    e.printStackTrace();
	}

14.2 日期时间格式

​ Calendar,jdk8.0新增的日期或时间的类:LocalDateTime, LocalDate, LocalTime

位于java.time包

​ 了解:LocalDateTime和Date之间的转换:

14.2.1 获取系统当前时间

 LocalDateTime d1 = LocalDateTime.now();

​ 14.2.2 指定时间

LocalDateTime d2 = LocalDateTime.of(2008, 11, 9, 13, 36, 22)

14.3 转换时间

14.3.1 字符串->时间

LocalDateTime d3=LocalDateTime.parse("2018-01-22T14:36:22")

​14.3.2 设定输出字符串的格式—格式化时间

DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")

14.3.3应用格式

String todayTime=nowTime.format(dtf); //应用格式并保存
LocalDateTime d4=LocalDateTime.parse("2000-12-20 21:40:22",dtf); //创建对象赋值并应用格式

14.4 获取某部分时间

 System.out.println("年="+nowTime.getYear());
 System.out.println("月="+nowTime.getMonth()); 
 System.out.println("日="+nowTime.getDayOfMonth());

14.5 加减时间段

必须创建新对象进行存储

LocalDateTime nowTime1=nowTime.minusYears(2);
LocalDateTime nowTime2=nowTime.plusMonths(2);

15 Math

Math 类位于java.lang包,含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。

Math

15.1 常量

System.out.println("PI="+Math.PI);
System.out.println("E="+Math.E);

15.2 random

//产生0-1之间的整数
double ran=Math.*random*();
//产生40-60之间的整数
int re;
double ran=Math.random();
int n=(int)(ran*20+40);???
re=(int)(ran*100)%21+40; // %21,余数为0.1.2……20之间的数值

​15.3 四舍五入

 long l=Math.round(2.86);
//上取整 ceil天花板
double d1=Math.ceil(123.5);
//下取整 floor
double d2=Math.floor(123.5);

15.4 小数位数固定

double d=16/3.0;
DecimalFormat df=new DecimalFormat("##.00");
String d1=df.format(d);

15.5 BigDecimal BigInteger

​ BigDecimal位于java.math包,包含不可变的、任意精度的有符号十进制数值

​ 大数值运算

 //创建对象并赋值
BigDecimal bd1 = new  BigDecimal("454543213245645142415412344543215");
BigDecimal bd2 = new BigDecimal("454543213245645142415453412344543215");
BigDecimal bd3=bd1.add(bd2); //运算

16 Enum

​ 枚举类位于java.lang包,是为了解决常量问题的,如:颜色,星期问题…

​ 常量大写;

16.1 创建

public enum MyWeek {
		//枚举
		SUN(0),MON(1),TUE(2),WED(3),THU(4),FRI(5),SAT(6);
		//私有化属性
		private int num;
		//私有化的 构造方法
		private MyWeek(int num){
			this.num=num;
		}
        //初始化赋值
		public int getNum() {
			return num;
		}
		public void setNum(int num) {
			this.num = num;
		}

16.2 应用

  public static void main(String[] args) {
		// 枚举取出所有值存储到数组里面
		MyWeek[] weeks = MyWeek.values();
		// 循环输出 (变量类型(名) 元素本身:数组名)
		for (MyWeek myw : weeks) {
			System.out.println(myw.getNum());
		}
		// 方法调用
		printweek(MyWeek.MON);
	}
	   // 输出方法
	public static void printweek(MyWeek weeks) {
		switch (weeks.getNum()) {
		case 0:
			System.out.println("米线");
			break;
		case 1:
			System.out.println("面条");
			break;
		case 2:
			System.out.println("火锅");
			break;
		case 3:
			System.out.println("冒菜");
			break;
		case 4:
			System.out.println("油泼");
			break;
		case 5:
			System.out.println("小炒");
			break;
		case 6:
			System.out.println("冰峰");
			break;
		default:
			System.out.println("不认识");
			break;
		}
	}
}

17 集合

数组(java.util包内)是用来存储对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用。

集合(对象类型可以不一样)的长度可变,可在多数情况下使用。

Collection

17.1 Collection接口

集合类的根接口,Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个子接口,就是Set和List。

17.1.1 List接口

List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。

实现类:

(1)ArrayList:新版本,线程不同步。

​ 底层结构是数组,查找速度快、增加删除速度慢。

​ 每次增长自身的50%

(2)LinkedList:新版本,线程不同步。

​ 底层结构是链表,查找速度慢、增加删除速度快。

(3)Vector:老版本,线程同步。

​ 底层结构是数组,每次增长自身的100%。

都可以添加null值,而且可以添加多个。

17.1.2 Set接口

无序、不可重复

(1)HashSet:类,实现了Set接口。

​ 是否是重复元素,由equals(), hashCode()决定。

可以添加null值,但最多只能添加一个。

为快速查找而设置的。

(2)TreeSet:类,实现了Set接口。

​ 添加到TreeSet中的元素是排好序的(排序规则由Comparable接口中的CompareTo()规定)所以,添加到集合中的元素必须实现Comparable接口。

​ 不能添加重复数据(由compareTo(), equals()决定)

​ 不能添加null值。

​ 为排序而设置的。

17.2 Map接口

以“键-值对”(Object key, Object value)的形式存储数据。

​ 无序、key不可以重复,value可以重复

(1)HashMap:类,实现了Map接口。

​ 无序的

​ key不能重复,value可以重复。如果key重复了,后一个值会替换掉前一个值。

​ key和value都可以添加null值。

新版本,线程不同步。

(2)HashTable:类,实现了Map接口。

​ 老版本,线程同步。

​ 不允许null值。

(3)TreeMap:类,实现了Map接口。

基于红黑树(Red-Black tree)Map集合。

​ 进行排序。

17.3 ArrayList

动态数组(大小可变数组) ArrayList:类,实现了List接口。

List接口的集合:有序、可重复

        //0.创建对象
		ArrayList al=new ArrayList();
		//1.添加元素 (返回值类型为boolean,添加成功与否)
		//(1)默认添加至末尾
		al.add("啤酒");
		al.add("饮料");
		al.add("矿泉水");
		//(2)添加至指定位置 编号从0开始
		al.add(1,"花生");
		//(*)直接输出,默认调用toString方法,已经重写
		System.out.println("al="+al);
		//2.求长度
		int len=al.size();
		System.out.println("元素个数len="+len);
		//3.读取元素
		String s1=(String)al.get(1);
		System.out.println("s1="+s1);
		//4.删除元素
		//(1)删除指定位置的元素
		String s2=(String) al.remove(2);
		System.out.println(s2+"被删除了");
		//(2)根据元素删除(如果有重复元素,一次只能删一个)
		boolean b=al.remove("花生");
		if(b){
			System.out.println("花生删除成功?"+b);
		}	
		//5.替换
		String s3=(String) al.set(0, "果啤");
		System.out.println(s3+"被替换了");
		//6.集合的遍历
		System.out.println("集合元素如下: ");
		int i;
		for(i=0;i<al.size();i++){
			String s=(String)al.get(i);
			System.out.println(s);
		}
		//7.清空
		al.clear();
		//8.判断是否为空
		if(al.isEmpty()){
			System.out.println("集合为空");
		}
		System.out.println("集合有内容");

(Dog类)

     //1.创建对象
		Dog d1=new Dog("小白","白色",1);
		//*类实现了接口,可以转成接口类型的对象;可以调用接口里的方法,类特加的	方法不能调用
		List ls=new ArrayList();
	//2.添加元素
		ls.add(d1);
		ls.add(1,d4);
	//3.删除
		//1)根据下标删除
		Dog d6=(Dog) ls.remove(0);
		System.out.println(d6+" 被删除了!");
		//2)根据元素删除(由equals()方法判断:不重写只有同一对象才可删除,重写就可以自定义删除条件)
		Dog d7=new Dog("小黑","黑色",2);
		System.out.println("-->"+d2.equals(d7));
		boolean b=ls.remove(d7);
		System.out.println("删除成功?"+b);

17.4 LinkedList

17.5 集合数据类型

​ 1.能否向集合中添加基本类型的数据?

​ 添加数据(装箱):基本类型–>包装类类型–>Object–>集合

​ 取数据(拆箱):集合–>Object–>包装类类型–>基本类型

​ 2.能否向同一个集合中添加多种类型的数据?

​ 可以,但是取数据时要注意类型。

​ 一般情况下,一个集合只存放一种类型的数据。

​ 3.一般用泛型编程对类型进行限制。(防止混装)

//规定只能导入Dog类 泛型限定

​ ArrayList al=new ArrayList();

17.6 遍历集合

​17.6.1 for循环

int i;
for(i=0;i<ls.size();i++){
	Dog dog=(Dog) ls.get(i);
	dog.show();
}

​17.6.2 for each循环

for(Dog d:ls){
	d.show();
}

​17.6.3 迭代器

Iterator<Dog> it=ls.iterator();
	while(it.hasNext()){
		Dog dog=it.next();
	    dog.show();
}

17.7 Collections类

对集合的操作方法

        Tiger t1=new Tiger("小红","红色",1);
		Tiger t2=new Tiger("小黑","黑色",2);
		Tiger t3=new Tiger("小黄","黄色",3);
		Tiger t4=new Tiger("小绿","绿色",4);
		Tiger t5=new Tiger("小蓝","蓝色",5);
		
		List<Tiger> ls=new ArrayList<Tiger> ();
		// 1.将所有指定元素添加到指定 collection 中。
		Collections.addAll(ls,t1,t2,t3,t4,t5);
		System.out.println("ls="+ls);
		//2.使用二分搜索法搜索指定列表,以获得指定对象。
		int i=Collections.binarySearch(ls,t1);
		System.out.println("i="+i);
		//3.将所有元素从一个列表复制到另一个列表。
		List<Tiger> ls1=new ArrayList<Tiger> ();
		ls1.add(null);
		ls1.add(null);
		ls1.add(null);
		ls1.add(null);
		ls1.add(null);
		ls1.add(null);
		Collections.copy(ls1, ls);
		System.out.println("复制ls1="+ls1);
		//4.使用指定元素替换指定列表中的所有元素。
		Tiger t6=new Tiger("小蓝","蓝色",6);
		Collections.fill(ls, t6);
		System.out.println("替换所有ls="+ls);
		//5.根据元素的自然顺序,返回给定 collection 的最大元素。
		Tiger t7=Collections.max(ls);
		System.out.println("最大元素t7="+t7);
		//6.使用另一个值替换列表中出现的所有某一指定值。
		Tiger t8=new Tiger("小白","白色",7);
		Collections.replaceAll(ls, t3, t8);
		System.out.println("替换ls="+ls);
		//7.反转指定列表中元素的顺序。
		Collections.reverse(ls);
		System.out.println("反转ls="+ls);
		//8.根据元素的自然顺序 对指定列表按升序进行排序。
		Collections.sort(ls);
		System.out.println("升序ls="+ls);
		//9.在指定列表的指定位置处交换元素。
		Collections.swap(ls, 0, 3);
		System.out.println("交换ls="+ls);
		//10.返回空的列表(不可变的)。
		List<String> s=Collections.emptyList();
		System.out.println("空的列表s="+s);

17.8 总结

集合的类或接口都位于:java.util.*;

(1)接口:Collection,存储线性数据

子接口:List、Set

List****接口实现类(有序,可重复,可以添加null值) 未重写toString方法

删除元素,根据元素内容是否相同(由equals方法)判断

ArrayList(动态数组)、增长比例为自身50% 已经重写toString方法

LinkedList(链表)(特有方法:add、get、remove --First、last)

Vector(动态数组)(增长比例为自身100%)

Stack

n Set****接口实现类(无序,不可重复,可以添加null值)

HashSet(重复与否由equals(), hashCode()决定、null<=1、快速查找)

TreeSet(重复与否由compareTo(), equals()决定且不能重复、默认排序,由Comparable接口中的CompareTo()规定、null=0、排序)

(2)接口:Map,存储键值对的形式

​ 实现类:HashMap、Hashtable、TreeMap

(3)Collections:类,对集合的操作方法

​ Arrays: 类,对数组的操作方法

​ equals 方法是 java.lang.Object 类的方法

(4)迭代器输出

​ 创建迭代器对象it,然后用集合调用iterator方法……

Iterator<Bank> it=lt.iterator();  
while(it.hasNext()){        
    Bank   b=it.next();     
    b.showMoney();  
}   

17.9 总结2

集合:

List:ArrayList, LinkedList, Vector, Stack

​ 有序 (有下标,可以通过下标访问元素)

​ 可重复

​ 可以添加null值

Set:接口,继承自Collection接口

​ 无序的

​ 不可重复

HashSet:类,实现了Set接口

​ 无序

​ 不允许添加重复元素(重复元素:equals(), hashcode())。

​ 可以添加null值,最多添加一个。

​ 适合于查找

TreeSet**:类,实现了Set接口**

​ 无序

​ 添加的元素会自动排序(排序规则:java.lang.Comparable接口中的compareTo())【所以,添加的元素所在的类必须要实现该接口】

​ 不允许添加重复元素(重复元素:compareTo(), equals())

​ 不允许添加null值。

​ 适合于排序

Map**:接口,**

​ 以“键-值对”的形式存储数据

​ 无序的

​ key不允许重复,value可以重复

HashMap**:类,实现了Map接口**

​ 无序的

​ key不允许重复,value可以重复(如果key重复了,后一个值会替换掉前一个值)

​ 新版本,线程不同步

​ 允许null的键和null的值。

Hashtable**:类**,实现了Map接口

​ 老版本,线程同步

​ 不允许null的键和null的值。

Collections**:类,对Collection集合的基本操作。**

18 I/O流

18.1 I/O:输入输出

​ 位于java.io包。

​ 需要掌握的类:File, InputStream, OutputStream, Reader, Writer

流:数据,数据源(保存数据的地方,如:文件、内存、数据库、网络)与程序之间

18.1.1 根据方向

输入流、输出流。

​ (1) 输入流:数据源–>程序 读操作

​ 跳过指定的字节:skip(n);

​ read()

​ close()

​ (2) 输出流:数据源<–程序 写操作

​ 默认在开头写。

​ 如果要在末尾追加:new FileOutputStream(file, true);

​ write()

​ flush():清空缓冲区

​ close()

18.1.2 根据操作单位

字节流:以字节为操作单位,可以操作任何类型的文件;默认不带缓冲区。

字符流:以字符为操作单位,只能操作文本型的文件;默认都带缓冲区。

18.2 File类

表示文件或文件夹 目录

18.3 字节流

以字节为操作单位,可以操作任何类型的文件。默认不带缓冲区。

根类:InputStream, OutputStream (抽象类)

子类:FileInputStream, FileOutputStream

​ BufferedInputStream, BufferedOutputStream(缓冲流,带缓冲区,效率高)

18.4 流的基本操作

1)	保存数据源 
		File file=new File("D:/workspace/Day01/read/paper.txt");
2)	建立流对象 
		FileInputStream fis=null; fis=new FileInputStream(file);
3)	读或写操作
		byte [] bt=new byte[1024];
	    int n;
		while((n=fis.read(bt))!=-1){
				String s=new String(bt, 0, n);
				System.out.println(s);
		}
4)	关闭流对象 fis.close();
--------------------------------------------------------------------------
输入流的操作:读
字节流:InputStream,OutputStream
子类:FileInputStream,FileOutputStream
FileInputStream:
	创建对象:new FileInputStream(String pathname);
	读:
	跳过指定的字节:skip(int n);
	关闭:close()
FileOutputStream:
	创建对象:new FileOutputStream(String pathname); //从头开始写
			new FileOutputStream(String pathname, true); //向末尾追加
	写:
	关闭:close()

18.5 缓冲字节流

BufferedInputStream, BufferedOutputStream

带缓冲区,效率高。

输出流的方法:

返回值类型为void,flush() 刷新此输出流并强制写出所有缓冲的输出字节

输出流输出结束时一定要调用flush()方法。

18.6 字符流

是以字符为操作单位,只能操作文本文件。默认都带缓冲区

根类:Reader, Writer (抽象类)

子类:FileReader, FileWriter

​ BufferedReader, BufferedWriter

(String readLine() )

18.7 字符字节转换流

​ 输入流InputStreamReader:字节–>字符

​ 输出流OutputStreamWriter:字符–>字节

18.8 序列化(串行化)

(对象流)序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。

18.8.1 将对象流化的过程

序列化:将对象转换成流 (输出流:ObjectOutputStream)

反序列化:将流还原成对象 (输入流:ObjectInputStream)

要被序列化的对象所在的类必须实现Serializable接口,此接口没有方法或字段,是一个声明性接口,表示实现此接口的类可以被序列化。

18.8.2 序列化ID

这个序列化ID起着关键的作用,它决定着是否能够成功反序列化!简单来说,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

当我们一个实体类中没有显示的定义一个名为“serialVersionUID”、类型为long的变量时,Java序列化机制会根据编译时的class自动生成一个serialVersionUID作为序列化版本比较,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID。譬如,当我们编写一个类时,随着时间的推移,我们因为需求改动,需要在本地类中添加其他的字段,这个时候再反序列化时便会出现serialVersionUID不一致,导致反序列化失败。那么如何解决呢?便是在本地类中添加一个“serialVersionUID”变量,值保持不变,便可以进行序列化和反序列化。

private static final long serialVersionUID = 4647012828877518301L;

决定是否能正确的反序列化。

序列化ID相同,表示类的版本一致。

18.8.3 对象序列化特点

1 、 静态属性不能被序列化。

2、当不希望类中的某个字段被序列化时,应用transient表示这个字段,如:private transient int age;

3、如果某个类能够被序列化,其子类也可以被序列化。

4、如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化。

5、对于父类的处理,如果父类没有实现串行化接口,则其必须有默认的构造函数(即没有参数的构造函数)。否则编译的时候就会报错。在反串行化的时候,默认构造函数会被调用。

19 内部类

19.1 概念

​ 内部类:将一个类的定义放在另一个类的定义内部,这就是内部类。

19.1.1 优点

​ 每个内部类都能独立地继承一个(接口的)实现,无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。利用内部类提供的、可以继承多个具体或者抽象的类来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

19.1.2 特性

内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。

在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。

创建内部类对象的时刻并不依赖于外围类对象的创建。

内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。

内部类提供了更好的封装,除了该外围类,其他类都不能访问。

19.2 内部类使用(基础)

19.2.1 访问范围

内部类可以访问所在外部类的所有成员,包括私有的。

public class Outer1 {
	private int a = 1;
	int b = 2;
	public int c = 3;
	class Inner {
		public void show() {
			System.out.println("Outer1:a=" + Outer1.this.a);
			System.out.println("b=" + b);
			System.out.println("c=" + c);
		}
	}
}
Outer1:a=1    b=2  c=3 

19.2.2 静态内部类

只能访问所在外部类的静态成员

public class Outer2 {
	private int a=1;
	int b=2;
	public static int c=3;
	static class Inner{
		private int d=4;
		public void show(){
		System.out.println("a="+a); //访问不到 ××
		System.out.println("b="+b); //访问不到 ××
		System.out.println("c="+c);
		System.out.println("d="+d);
		}
	}
}
c=3   d=4

19.2.3 局部内部类

放在某个方法内,只有该方法可以使用

public class Outer3 {
	public int add(int a, int b) {
			class Inner {
			public int addi(int x, int y) {
				return x + y;
			}
		}
		Inner i = new Inner();
		int c = i.addi(a, b);
		return c;
	}
}

19.3 内部类使用(进阶)

package demo01;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class DogTest2 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<String> list1=Arrays.asList("aa","bb","cc","dd");
		System.out.println("list1="+list1);
		
		Dog d1=new Dog("one","red",2);
		Dog d2=new Dog("two","green",11);
		Dog d3=new Dog("three","blue",4);
		Dog d4=new Dog("four","yello",3);
		
		List<Dog> list=Arrays.asList(d1,d2,d3,d4);
		System.out.println("list="+list);
	
		Dog[] dogs=new Dog[]{d1,d2,d3,d4};
	
//		Arrays.sort(dogs);//Dog类实现Comparable接口
		Arrays.sort(dogs, new Comparator<Dog>() {
			@Override
			public int compare(Dog o1, Dog o2) {
				// TODO Auto-generated method stub
				return o2.getAge()-o1.getAge();
			}
		});
		for(Dog d:dogs){
			d.show();
		}
	}
}

//求年龄最大值


<Dog> Dog java.util.Collections.max(Collection<? extends Dog> coll, Comparator<? super Dog> comp)
//此方法传入一个对象类的集合,以及一个比较器创建对象类
        Dog d1=new Dog("小白","白色",1);
		Dog d2=new Dog("小黑","黑色",2);
		Dog d3=new Dog("小灰","灰色",5);
		Dog d4=new Dog("小棕","棕色",4);
		Dog d5=new Dog("小黄","黄色",3);
		List<Dog> list=new ArrayList<Dog>();
		Collections.addAll(list, d1,d2,d3,d4,d5);
Dog dmax=Collections.max(list,new Comparator<Dog>(){
			@Override
			public int compare(Dog o1, Dog o2) {
				// TODO Auto-generated method stub
				return o1.getAge()-o2.getAge();
			}
		});
		System.out.println("dmax="+dmax); 

20. 数据库连接

20.1 JDBC

20.1.1 概念

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API(应用程序接口),可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

20.1.2 JDBC架构图

JDBC

​ 其中,JDBC API,提供者:sun公司,主要内容:供程序员调用的接口与类,集成在java.sql和javax.sql包中,如:DriverManager类*、Connection接口、Statement接口*、ResultSet接口。

​ DriverManager ,提供者:sun公司,作用:载入各种不同的JDBC驱动。

​ JDBC 驱动,提供者:数据库厂商,作用:负责连接各种不同的数据库。

20.1.3 应用流程

JDBC API可做三件事:与数据库建立连接、执行SQL 语句、处理结果。

在这里插入图片描述

其中,DriverManager :依据数据库的不同,管理JDBC驱动

Connection :负责连接数据库并担任传送数据的任务

Statement :由 Connection 产生、负责执行SQL语句

ResultSet:负责保存Statement执行后所产生的查询结果

20.2 实际操作

步骤:

(1)将数据库驱动添加到项目中去

(2)编码

1.加载驱动 Class.forName("com.mysql.jdbc.Driver");
2.建立连接 
	url字符串的格式:主协议:子协议:名称
	//  注释: String url="jdbc:mysql://localhost(本机地址)/mydb";
	String url="jdbc:mysql://127.0.0.1:3306/mydb";
	Connection conn=DriverManager.getConnection(url, "root", "123456");
(封装—写入方法调用)
3.准备sql语句,Statement对象
		String sql="update stu set age=18, addr='北京' where sno=104";
		PreparedStatement 	pstmt=conn.createStatement();
			pstmt=conn.prepareStatement(sql);
			//设置参数
			pstmt.setInt(1, num);
4.执行
			//executeUpdate():适用于DML语句(insert, update, delete)int
			// executeQurey():适用于DQL语句(select)ResultSet
			//返回值表示受影响的行数、查询结果
			//rs.next检测是否存在下一行,如果有返回true,并指向该行,
			// rs.get(“列名”):读取某列的值,可以写列号(不推荐使用)、列名
int n=pstmt.executeUpdate(sql);	rs=pstmt.executeQuery();
			
5.处理结果
		System.out.println(n);
			if(n>0){
				System.out.println("更新成功");
			}else{
				System.out.println("更新失败!");
			}	
      while(rs.next()){
          int num=rs.getInt("sno");
          String name=rs.getString("sname");
          String sex=rs.getString("sex");
          int age=rs.getInt("age");
          String addr=rs.getString("addr");
           System.out.println(num+"\t"+name+"\t"+sex+"\t"+age+"\t"+addr);
	    }
6.关闭资源
关闭顺序与使用顺序相反
		finally{
					DbConn.closeRs(rs); //执行结果
					DbConn.closeStmt(pstmt); //sql语句,结果
					DbConn.closeConn(conn); // 断开连接
		}

21. 线程

21.1 概念

进程:正在运行的程序。需要地址空间,占用cpu,内存。多任务管理系统。

线程:是进程中的一个实体,是能被系统独立调度和分配的最小的单位。一个进程可以包含多个线程。

优点:1)提高效率 2)提高资源的利用率(cpu)

对比

1)是否占用资源:进程需要占用资源,线程不需要单独的资源,可以共享所在进程的资源。

2)创建或撤销的开销:进程大,线程小

3)进程是重量级组件,线程是轻量级组件。

4)进程可以独立存在,线程必须依赖于进程(寄生在进程中)

21.2 实现

21.2.1 继承自Thread类

​ 1》创建类Dog,继承自Thread类,重写run()

​ 2》启动线程:先创建Dog类的对象,调用该对象的start()

​ 案例:Dog d1=new Dog();

​ d1.start();

21.2.2 实现Runnable接口

​ 1》创建类Cat,实现Runnable接口,重写run()

​ 2》启动线程:创建Cat类的对象c1,创建Thread类的对象t1,调用t1的start()

​ 案例:Cat c1=new Cat();

​ Thread t1=new Thread(c1);

​ t1.start();

21.3 对比

1)从java设计来说,没有区别

2)继承的方式:启动线程简单

实现接口的方式:不受单继承的限制,更加灵活。可以实现资源共享。

一般情况下,实现接口的方式可以完成任何的多线程工作。

21.4 线程的优先级

setPrrity(int newPriority):设置线程的优先级

数字:1—10, 数字越大,优先级越高。 默认为5

静态常量:Thread.MAX_PRIORITY,Thread.MIN_PRIORITY

21.5 线程的生命周期

线程有几种状态:

新建状态(new)

就绪状态(Runnable)

运行状态(Running)

阻塞状态(Blocked)

死亡状态(Dead)

转换图如下:

在这里插入图片描述

线程的状态转换

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

​ 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

​ 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

​ 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

如需要实现这样的功能:编写一个程序,模拟一个机票售票系统:有3个售票点,在1天卖出2000张票。

多线程并发优点:提高效率

​ 缺点:数据不安全

21.6 线程同步

同步的代码,一个线程没有执行完之前,不允许其他线程执行。

​ 优点:安全

​ 缺点:效率低

注意:如果不存在安全性的问题,不需要加同步

关键字:同步,互斥锁:synchronized

Object:wait(), notify(), notifyAll() 这三个方法必须用在同步代码中(Synchronized

同步代码块:synchronized(对象){………}

同步方法:public synchronized 返回值类型 方法名(){…………………}

21.7 Thread类的常用方法

1.run():线程执行时调用该方法

  1. start():启动一个新线程;调用该线程的run();

  2. setName(), getName()

  3. setPriority(), getPriority() 优先级

  4. static Thread currentThread() 获取当前线程对象

  5. sleep():休眠,单位:毫秒

​ 休眠会转入阻塞状态,休眠结束后会自动回到就绪状态。

  1. 线程的结束

​ 尽量自然结束。

​ void interrupt() 中断线程。

​ ·void stop() 结束线程(已过时)

  1. void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。

​ 生命周期最长的那个线程

​ 比如:垃圾回收线程

​ 一般是服务线程,比如:垃圾回收,打印日志…….

  1. join() 等待该线程终止。

  2. yield() 暂停当前正在执行的线程对象,并执行其他线程。

​ 线程如果执行了yield()方法,会回到就绪状态,参与cpu的竞争

  1. wait():等待, 转入阻塞状态,等待其他线程通知它才会回到就绪状态。

  2. notify():唤醒、通知,通知该对象锁等待队列中的一个线程

​ notifyAll():唤醒所有的等待该锁的线程

21.8 线程池

​ 我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在Java中可以通过线程池来达到这样的效果。Java里面线程池的顶级接口是 Executor,不过真正的线程池接口是 ExecutorService,ExecutorService 的默认实现是 ThreadPoolExecutor;普通类 Executors 里面调用的就是 ThreadPoolExecutor

21.8.1 Executors

(1)newCachedThreadPool

是一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute() 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。

(2)newSingleThreadExecutor

创建是一个单线程池,也就是该线程池只有一个线程在工作,所有的任务是串行执行的,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

(3)newFixedThreadPool

创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

(4)newScheduledThreadPool

创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

21.8.2 线程池优点

(1)避免线程的创建和销毁带来的性能开销。

(2)避免大量的线程间因互相抢占系统资源导致的阻塞现象。

(3)能够对线程进行简单的管理并提供定时执行、间隔执行等功能。

21.9 BlockingQueue

阻塞队列

22 Servlet

22.1 B/S与C/S

​ C/S:client/server,QQ,手机app

​ (需要安装客户端软件)

​ B/S:brower/server, 网银,淘宝

22.2 部署web项目

​ 服务器:Tomcat

22.3 Servlet

22.3.1 servlet

是一个java程序,可以处理客户端的请求并给出响应。

22.3.2 servlet的配置

 <servlet>
 	 	<servlet-name>TestServ</servlet-name>
  		<servlet-class>servlet.TestServ</servlet-class>
 	 </servlet>
  
  	<servlet-mapping>
  		<servlet-name>TestServ</servlet-name>
  		<url-pattern>/test.action</url-pattern>
 	 </servlet-mapping>
	// 注意:两个<servlet-name>名称必须一致。

通过浏览器地址访问:

​ 地址–>匹配查看, 再根据中的找到要执行的类。

也可以通过注解去配置:

@WebServlet("/login.action")

单例模式

线程安全的吗? 不安全,所以一般不要在servlet中设置属性。

22.3.3 生命周期

​ 分为几个阶段:

(1)实例化:调用构造方法(1次)

​ Servlet 容器创建 Servlet 的实例

​ Servlet容器负责加载和实例化Servlet,当客户端发送一个请求时,Servlet容器会查找内存中是否存在Servlet实例,如果不存在则创建,如果存在则取出响应。一个servlet就只有一个实例(单例模式)。

(2)初始化:调用init()方法(1次)

​ 该容器调用 init() 方法

​ Servlet容器加载好Servlet后,必须进行初始化,初始化时可以设置数据库连接参数,建立JDBC连接,或者是建立对其他资源的引用。在初始化阶段,init()方法被调用。

(3)服务:调用service()方法

​ 如果请求 Servlet,则容器调用 service() 方法。(根据请求方式,doGet(), doPost())(每请求一次就调用一次)

​ Servlet被初始化以后,就处于能响应请求的就绪状态,每个对Servlet的请求都由一个Servlet Request对象代表,Servlet给客户端的响应由一个Servlet Response对象代表。当客户端有一个请求时,Servlet容器将Servlet Request和Servlet Response对象都转发给Servlet,这两个对象以参数的形式传给service()方法。在service()方法内,对客户端的请求方法进行判断,如果为get方法提交,则调用doGet()处理请求,如果为post方法提交,则调用doPost()方法处理请求。

(4)销毁:调用destroy()方法(1次)

​ 销毁实例之前调用 destroy() 方法

​ Servlet的实例是由Servlet容器创建的,所以实例的销毁也是由容器来完成的。Servlet容器判断一个Servlet应当被释放时(容器关闭或需要回收资源),容器必须让Servlet释放其正在使用的任何资源,这些都是由容器调用Servlet的destroy()方法实现的。Destroy()方法指明哪些资源可以被系统回收,而不是由destroy()方法直接进行回收。

23 MVC模式

23.1 概念

V:view,视图

C:controller,控制器

​ 接收请求,给出响应

​ servlet

M:model,模型,数据模型和业务模型

​ V 发送请求 C 接收请求,调用M处理,得到结果,响应给V

23.2 JSP

​ Java Server Pages:在html代码中嵌入java脚本。Jsp是在servlet的基础上产生的。作用:可以处理用户的请求,并给出响应

23.2.1 常用的脚本

​ <%@ %>:指令

​ <% %>:java脚本

​ <%= %>:表达式

23.2.2 page指令

​ <%@ page language=“java” import=“java.util.*” pageEncoding=“utf-8”%>

​ language:指定脚本语言

​ import:导入包

​ pageEncoding:编码方式

23.2.3 Jsp的执行过程

​ 1)翻译:将jsp文件翻译成.java文件

​ 2)编译:将.java文件编译成字节码(.class)文件

​ 3)执行:以html页面的形式返回,响应给用户

​ 第二次请求jsp文件时,直接将字节码文件执行(只需要执行即可),所以,同样的一个jsp文件,第一次请求时速度慢,以后再请求速度就快了。

23.2.4 从Servlet向jsp发送数据

request.setAttribute("userList", list);
//转发   request.getRequestDispatcher("main_user.jsp").forward(request, response);
jsp获取数据:
List<Users> list=(List<Users>)request.getAttribute("userList"); 

23.3 out、request、respone

1)out:(PrinterWriter out=response.getWriter())
	out.print();
2)request:(HttpServletRequest)请求
	//设置编码方式
	request.setCharacterEncoding(“utf-8);
	//获取表单数据
	String name=request.getParameter(“控件名”);
	String[] vals=request.getParamerterValues(“chb”);
	//属性
	request.setAttribute(“属性名”,  Object);
	Object o=request.getAttribute(“属性名”);
	//转发
	request.getRequestDispatcher("main_user.jsp");
	(完整代码)
request.getRequestDispatcher("main_user.jsp").forward(request, response);
3)response:(HttpServletResponse)响应
	//重定向
response.sendRedirect(“url”);
	//设置页面类型
	response.setContentType(“text/html; charset=utf-8);
	response.setCharacterEncoding(“utf-8);

23.4 项目

V:webcontent

C:(servlet)….servlet(获取请求的数据,调用M来处理,响应)

M:service

​ dao

​ dbUtil

​ entity

高内聚、低耦合

24. EL、JSTL

24.1 EL

Exception Language
${变量名 }
运算符:
+-*/, %
\>, <, >=, <=, ==, !=
and, or, not 或  &&, ||, !

24.2 JSTL

1)要添加jstl的jar包      eg: jstl-1.2.jar
(2)导入标签库
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>3)常用
 输出变量:
<c:out value="${username }">
</c:out>
 选择:
	<c:if test="${book.price>60 }">
		太贵
	</c:if>
 多种选择:
		设置,并赋值:<c:set var="a" value="60"></c:set>
	<c:choose>
		<c:when test="${book.price<50 }">便宜</c:when>
		<c:when test="${book.price<a }">有点贵</c:when>
		<c:otherwise>太贵</c:otherwise>
	</c:choose>
 循环:
集合
		<c:forEach items="${list }" var="bk" >
			${bk },
		</c:forEach>
		数组
		<c:forEach items="${arr }" var="a" varStatus="vs" >
			${vs.index }:	${a }--
		</c:forEach>
 1--100输出:
	<c:forEach begin="1" end="100" step="5" var="i">
		${i },
	</c:forEach>

25 session

​ 会话:浏览器与服务器的一次通话,包括多次的请求和响应。

​ session用来保存会话信息。Jsp:session是内置对象,直接用。(http协议:无记忆性)session信息存储在服务器端

25.1 类型

Servlet:类型:HttpSession
创建:HttpSession session=request.getSession(); //同参数为true
request.getSession(true); //获取该请求的session,如果没有则创建
request.getSession(false);	//获取该请求的session,如果没有则返回null

25.2 用法

session.setAttribute("uname", name);
String name=(String)session.getAttribute(“uname”);

25.3 生命周期

25.3.1 创建

​ 第一次访问该网站

​ 每个用户都有自己的session,在访问该网站的过程中都可以共享。不能访问别人的session。

​ 一般session中不存大量的数据。

25.3.2 销毁​

A.与浏览器相关,浏览器关闭,session结束。
B.超过最大访问时间间隔,session结束。
	session.setMaxInactiveInterval(5);
C.失效或移除某项session
    //移除某项session
	//session.removeAttribute("uname");
	//使session失效
	session.invalidate();

25.4 用处

​ 可以控制访问,记住某些信息,……

​ (一般session中不存大量的数据。)

25.5 页面数据到后台

25.5.1 表单提交

<form ><input type=”submit” …/>
</from>

get:不安全,数据量有限制,响应速度快

post:安全,无限制,速度慢

25.5.2 超链接传参数​

 …/bookdetail.jsp?参数名=参数值&参数名=参数值

25.6 转发和重定向

25.6.1 重定向:客户端跳转

  response.sendRedirect(“index.html”);

​ 因为要有客户端的往返,速度慢,需要网络,不安全

​ 可以是任意的url

​ request作用域不能继续传递

25.6.2 转发:服务器跳转​

request.getRequestDispatcher(“index.html”).forward(request, response);

​ 直接服务器内部跳转,速度快。

​ 只能局限于同一个服务器的地址 地址栏不变

​ 可以使request的作用域继续传递

25.7 servlet写验证码

25.8 Cookie

存在客户端

保存用户名、密码,网站风格……

25.8.1 基本用法

//1.创建cookie对象
				Cookie ck1=new Cookie("ck_name", name);
				Cookie ck2=new Cookie("ck_pwd", pwd);
//2.设置保存时间
				ck1.setMaxAge(10*60);
				ck2.setMaxAge(10*60);
//3.添加到客户端
				response.addCookie(ck1);			
				response.addCookie(ck2);

如果保存时间设置为0,表示删除该cookie;
如果保存时间设置为负数,则不保存。
Cookie[] cks=request.getCookies();
		for(Cookie ck:cks){
			out.print(ck.getName()+"-->"+ck.getValue()+"<br/>");
		}
cookie中不能存中文,如果要存,可以用加密或解密方法进行转换:
String s12=URLEncoder.encode(s1, "utf-8");			
			String s2=URLDecoder.decode(s12, "utf-8");

25.8.2 session与cookie的对比

  1. 存储:session存在服务器上,cookie存在客户端

  2. 安全性:session更安全

  3. 网络:session不需要,cookie需要经过网络

  4. 时间:

​ session.setMaxInactiveInterval(10); 指间隔时间,每次访问了之后会重新计时。 浏览器关闭session就结束。

​ cookie.setMaxAge(10); 指存在时间,关闭浏览器或电脑都没有影响。

25.9 application

全局共享的变量。

可以统计用户访问量

在Jsp中,application是内置对象

在servlet中,

ServletContext app=this.getServletContext();

常用方法:​

application.setAttribute(“name”,  value);
Object o=application.getAttribute(“name”);
application.removeAttribute(“name”);

25.10 读文件

25.10.1 属性文件

Properties

25.10.2 配置文件

//读取配置文件(全局)
String address=this.getServletContext().getInitParameter("address");
//读取配置文件(局部)
String phone=this.getServletConfig().getInitParameter("phone");

this.getServletContext()---Jsp中的application
this.getServletConfig()---Jsp中的config

25.11 Cookie、session、application

sessionCookieapplication
保存会话信息(本用户)(本用户[电脑有关])全局的
服务器客户端服务器
jsp的内置对象(HttpSession session=request.getSession())不是是(ServletContext app=this.getServletContext)
安全不安全
间隔访问时间生存时间

25.12 Jsp的九大内置对象

out:  向页面输出 response.getWriter();
request:请求 HttpServletRequest
response:响应  HttpServletResponse 
session:保存会话信息 HttpSession
application:全局的变量  ServletContext
config:配置信息 ServletConfig
page:页面信息   
exception:异常
pageContext:页面上下文,

26 过滤器 Filter

​ 功能是在浏览器与服务器之间进行过滤、拦截,不是处理请求、响应。

26.1 过滤路径

26.1.1 @WebFilter("*.action")

(注解的方式配置过滤路径)

​ 过滤所有路径:/*

​ 过滤test文件下的文件:/test/*

​ 过滤所有的.action:*.action

​ 过滤多个路径:@WebFilter( { “/front/shopCar.jsp” , “/front/order.jsp” } )

26.1.2 过滤链

注解方式配置:由类名顺序决定先后

​ 在web.xml中配置:

   <filter>
  		<filter-name>f3</filter-name>
  		<filter-class>com.xxy.bs.filter.Filter3</filter-class>
  </filter>
  <filter-mapping>
  		<filter-name>f3</filter-name>
  		<url-pattern>/test/*</url-pattern>
  </filter-mapping>

​ xml文件配置的顺序:由的先后顺序决定

26.2 作用

​ 解决乱码问题、权限的验证、日志信息、……….

27 监听器Listener

监听某种事件

28 ajax

28.1 ajax是什么?

  1. asynchronous javascript and xml:异步的js和xml

  2. 它能使用js访问服务器,而且是异步访问

  3. 服务器给客户端的响应一般是整个页面,一个html完整页面!但在ajax中因为是局部刷新,那么服务器就不用再响应整个页面!而只是数据!

text:纯文本

xml:大家都熟悉

json:它是js提供的数据交互格式,它在ajax中最受欢迎!

28.2 ajax的优缺点

28.2.1 优点

异步交互:增强了用户的体验!

性能:因为服务器无需再响应整个页面,只需要响应部分内容,所以服务器的压力减轻了!

28.2.2 缺点

ajax不能应用在所有场景!

ajax无端的增多了对服务器的访问次数,给服务器带来了压力!

28.2.3 步骤

创建对象:XMLHttpRequest  xmlHttp

建立连接:open(“Get”,”url”, true);

发送:send(data);

接收结果:xmlHttp.onreadystatechange=function(){    }

document.getElementById("btn2").onclick=function(){
		//ajax请求
		//1.创建XMLHttpRequest的对象
		var xmlHttp=new XMLHttpRequest();
		//2.建立连接
		//参数:1:请求方式,2:请求地址,3:是否是异步
		var val=document.getElementById("id2").value;
		xmlHttp.open("POST","../ajax01.action",true);
		//3.发送
		//设置请求头(post请求需要)
	xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
		xmlHttp.send("uname="+val);//get请求写null
		//4.监听状态改变
		xmlHttp.onreadystatechange=function(){
			if(xmlHttp.readyState==4 && xmlHttp.status==200){
				alert(xmlHttp.responseText);
			}
		}
	}

28.3 xmlHttp

在xmlHttp对象的一个事件上注册监听器:onreadystatechange

* xmlHttp对象一共有5个状态:

​ > 0状态:刚创建,还没有调用open()方法;

​ > 1状态:请求开始:调用了open()方法,但还没有调用send()方法

​ > 2状态:调用完了send()方法了;

​ > 3状态:服务器已经开始响应,但不表示响应结束了!

​ > 4状态:服务器响应结束!(通常我们只关心这个状态!!!)

* 得到xmlHttp对象的状态:

​ > var state = xmlHttp.readyState;//可能是0、1、2、3、4

* 得到服务器响应的状态码

​ > var status = xmlHttp.status;//例如为200、404、500

* 得到服务器响应的内容1

​ > var content = xmlHttp.responseText;//得到服务器的响应的文本格式的内容

​ > var content = xmlHttp.responseXML;//得到服务器的响应的xml响应的内容,它是Document对象了!

28.4 JSON

JSON是JavaScript Object Notation的缩写,可见JSON来源于JavaScript。

​ JSON数据是一系列键值对的集合。

JSON是一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。业内主流技术为其提供了完整的解决方案,获得了当今大部分语言的支持,从而可以在不同平台间进行数据交换。JSON采用兼容性很高的文本格式。

28.5 jquery

$.ajax({
		type: “post”,
		url: “”,
		async: true,
		data: {name: “value”},
		success: function(data){
		},
		dataType:”html”
});
	$.post(url, {data}, function(){  }, “html”);

29 xml

29.1 XML介绍

​ XML:Extensible Markup Language,可扩展标记语言

(1)什么是可扩展标记语言?

可扩展标记语言是一种很像超文本标记语言的标记语言。

它的设计宗旨是传输数据,而不是显示数据。

它的标签没有被预定义。您需要自行定义标签。

它被设计为具有自我描述性。

它是W3C的推荐标准。

(2)可扩展标记语言和超文本标记语言之间的差异

它不是超文本标记语言的替代。

它是对超文本标记语言的补充。

它和超文本标记语言为不同的目的而设计:

它被设计用来传输和存储数据,其焦点是数据的内容。

超文本标记语言被设计用来显示数据,其焦点是数据的外观。

超文本标记语言旨在显示信息,而它旨在传输信息。

对它最好的描述是:它是独立于软件和硬件的信息传输工具。

(3)可扩展标记语言是W3C的推荐标准

XML 于 1998 年 2 月 10 日成为 W3C 的推荐标准。

29.2 XML解析对比

29.2.1 DOM解析

首先读取整个xml文件

解析全部的节点生成dom树

文件比较小的情况下

29.2.2 SAX解析

解析速度比较块

一般适用于大文件

进行读取文件

29.2.3 DOM4J解析

DOM4J是一个开源的,基于Java的库来解析XML文档,它具有高度的灵活性,高性能和内存效率的API

性能比较高

推荐使用

29.3 DOM4J解析

1)创建SAXReader类的对象
		SAXReader reader=new SAXReader();2)将xml文件读入
Document document=
reader.read(TestXml1.class.getResourceAsStream("/test1.xml"));3)读取根元素:
Element root=document.getRootElement();
System.out.println("元素名:"+root.getName());
System.out.println("元素值:"+root.getText());
System.out.println("属性的个数:"+root.attributeCount());
System.out.println("属性值:"+root.attributeValue("class1"));4)读取某个子元素:
Element nameEle=ele.element("name");
Element ageEle=ele.element("age");
读取所有的子元素:
List<Element> eleList=root.elements();

30 Java-EE复习

http://localhost:8080/demo/index.jsp

JavaBean(Entity),Dao,Service

Web****组件:JSP,Servlet,Filter,Listener

30.1 A如何去B?

l 表单提交

l 超链接

l 重定向

l 请求转发

30.2 A如何给B传参呢?(Object)

l 表单元素value----------string , Object(session,application)

l ?传参string, Object(session,application)

l ?传参string, Object(session,application)

l request,Object(request,session,application)

30.3 项目开发流程

(1)建库建表--------------《项目的设计文档》

(2)创建项目

(3)根据表创建实体类

(4)引入项目所需资源

l 静态资源:页面,css,js,images

l 工具类

(5)Dao(难点)

l 几个?UserDao,OrderDao,ProductDao,VoteDao

l Dao接口和Dao实现类

​ 投票:添加方法

​ 查询:票数和百分比

(6)Service

​ 根据程序功能实现业务方法,所有的业务都应该在service中完成,供Servlet调用。

(7)Servlet

l 接收请求参数

l 调用业务

l 重定向或请求转发

(8)JSP

l 表单

l 展示结果数据(JSTL&EL)

快速原型法

30.4 同步、异步

​ 同步:发送请求后,必须等待服务器响应完成才能进行下一步的操作。

​ 异步:发送请求后,不用等待响应结果,可以继续下一个操作。

405:请求方式与Servlet处理方式不一致!!!

404: 未找到

重定向是301、302

访问被拒绝是401

未找到是404

history.back();============history.go(-1);

history.forward();============history.go(1);

30 反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制**。

30.1 优点

1、反射提高了程序的灵活性和扩展性。

2、降低耦合性,提高自适应能力。

3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

30.2 缺点

​ 1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。

2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

30.3 类的加载

a) 将硬盘或者是网络上的class文件通过加载器加载到内存中,并解析class文件 最终产生一个Class对象的过程

b) 加载器

​ i. Bootstrap Classloader启动类加载器

​ ii. ExtClassLoader(extetion)扩展类加载器

​ iii. AppClassLoader

30.4 双亲委派(托)机制

1)得到Class对象的方法:
	Class cla1=Class.forName(“com.entity.Stu”);
	Class cla2=Stu.class;
	Class cla3=s1.getClass();2)获取属性、构造方法、方法
	Field[]  fs=cla.getDeclaredFields();//可以获取所有的,包括私有的
	Field[]  fs=cla.getFields();
	Constructor[] cons=cla.getConstructors();
	Constructor[] cons=cla.getDeclaredConstructors();
	Method[] methods= cla.getMethods();	
	Method[] methods2 = cla.getDeclaredMethods();
Method m=cla.getDeclaredMethod("setName",java.lang.String.class);	
	调用方法:m.invoke(s1, "Tom");  //s1.m的名字(“tom”);
	创建类的对象(必须要有无参的构造方法):
    Class cla=Stu.class;
    Object s1=cla.newInstance();

31 SpringJDBC

Spring提供的持久层技术。框架,做持久层

33.1 配置jar包

在这里插入图片描述

33.2 使用

(1)配置数据源
	DriverManagerDataSource dataSource=new DriverManagerDataSource();
	dataSource.setDriverClassName("com.mysql.jdbc.Driver");
	dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/bookstore?useUnicode=true&characterEncoding=utf-8");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");2)建立连接
		JdbcTemplate tem=new JdbcTemplate(dataSource);3)JdbcTemplate类的执行方法
	1)更新(增、删、改):  返回值为整型
int n=tem.update(sql, bname,price,bid);	
	2)查询:
		//返回集合
List<Map<String, Object>>  list=tem.queryForList(sql);
List<Book> list=tem.query(sql, new BookRowMapper());
		//注意:RowMapper类中的列一定要<=select查询出来的列
//返回一个对象
Book bk=tem.queryForObject(sql, new BookRowMapper(), bid);
		//返回单个值
		int n=tem.queryForObject(sql, Integer.class, "%"+bname+"%");
		String bname=tem.queryForObject(sql, String.class, bid);
String sql="select bname from book";
List<String> list=tem.queryForList(sql, java.lang.String.class);
//批处理
String sql="insert into book(bname,price) values(?,?)";
			List<Object[]> list=new ArrayList<Object[]>();
			Object[] o1=new Object[]{"abc",77};
			Object[] o2=new Object[]{"def",88};
			Object[] o3=new Object[]{"ghi",99};
			list.add(o1);
			list.add(o2);
			list.add(o3);		
	批量修	int[] ns=tem.batchUpdate(sql, list);

32 文件上传

32.1 关于路径

//项目名
		String a1=this.getServletContext().getContextPath();
		String a4=request.getContextPath();
		//文件的实际路径
		String a2=this.getServletContext().getRealPath("imgs");
int a7=request.getLocalPort();
		String a8=request.getMethod();
		String a9=request.getProtocol();
		String a10=request.getRequestURI();
//url
		String a11=request.getRequestURL().toString();
//协议名
request.getScheme()  
		request.getServerName()  //主机名
String str=request.getScheme()+"://"+request.getServerName()+":"+request.getLocalPort()+request.getContextPath();
		System.out.println("str="+str);

32.2 检测是否登录

32.3 文件上传

32.3.1 页面

采用jquery的上传框架:

需要引入jquery的文件:ajaxfileupload.js

$.ajaxFileUpload({
			url:'uploadBimg.action',//处理图片的servlet地址
			secureuri:false,
			fileElementId:'fileId',//file控件的id【name与id必须相同】
			dataType:'HTML',//这里一定要大写,返回的数据类型
			success: function(data, status){
				//alert(data);
				$("#bimgId").val(data);
				$("#myImg").prop("src","../imgs/"+data);
				
			},
			error:function(data, status, e){
				alert(e);
			}
		
		});
		return false;

32.3.2 后台需要jar包

在这里插入图片描述

response.setContentType("text/html");
		DiskFileItemFactory factory=new DiskFileItemFactory();
		ServletFileUpload upload=new ServletFileUpload(factory);
		String fileName="";
		try {
			List<FileItem> list=upload.parseRequest(request);
			
			FileItem file=(FileItem) list.get(0);
			
			//System.out.println("list="+list);
			//System.out.println("file="+file);
			
			//取出文件名:
			fileName=file.getName();			
			System.out.println("fileName="+fileName);
			
			//输入流:将本地图片读入
			InputStream is=file.getInputStream();
			
			//输出流:存储到服务器的imgs文件夹下
			String filePathStr=request.getServletContext().getRealPath("imgs");
			System.out.println("filePathStr="+filePathStr);
			OutputStream os=new FileOutputStream(filePathStr+"\\"+fileName);
			//进行复制
			byte[] b=new byte[1024];
			int n;
			while((n=is.read(b))!=-1){
				os.write(b,0,n);
			}
			os.flush();
			
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		response.getWriter().print(fileName);

33 Java Web主流框架

33.1 Struts

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nzFi6t5C-1601729922299)(C:\Users\Zhuph\AppData\Roaming\Typora\typora-user-images\1601729503371.png)]

33.2 Spring、Hibernate

在这里插入图片描述

33.3 SSH(Struts、Spring、Hibernate)

在这里插入图片描述

33.4 MVC框架

33.4.1 MVC设计模式的一个实现

在这里插入图片描述

JSP+Servlet+JavaBean形式开发
JSP——View
Servlet——Controller
JavaBean——Model

l 优点 各司其职,互不干涉、有利于分工开发、 有利于组件重用
l 缺点:开发复杂,适合大型应用;不好控制,没有一个统一的规则 |

33.4.2 自定义MVC框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUE49I6l-1601729922340)(C:\Users\Zhuph\AppData\Roaming\Typora\typora-user-images\1601729676066.png)]

l 编写核心控制器(ControllerServlet)

截获所有请求

从请求的URL中分析功能

分发到相应的处理类中

根据处理结果进行跳转

l 编写处理类

Ø 编写处理类接口(Action)

Stringexecute(request,response)方法

编写处理类的实现类

xxxAction

l 分派代码有些繁杂,每每增加业务就需要修改ControllerServlet。

Action

中的execute()方法中直接引用页面名称作为跳转路径,如果页面名称发生改变,则需要修改代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值