百战程序员_ Java1573题
QQ群:
561832648
489034603
掌握80%年薪20万
掌握50%年薪10万
全程项目穿插, 从易到难,含17个项目
视频和资料持续更新,请关注www.itbaizhan.com
国内最牛七星级团队
马士兵、高淇等11位十年开发经验专家录制
目 录
百战程序员Java1573题 2
百战程序员介绍 3
JavaSE编程基础 9
第一章 初识Java 9
阶段项目课程1 11
第二章 数据类型和运算符 14
第三章 控制语句 17
第四章 数组 24
阶段项目课程2 27
第五章 面向对象 27
第六章 异常机制 39
阶段项目课程3 41
第七章 常用类 41
第八章 容器 47
阶段项目课程4 57
第九章 IO流技术 58
第十章 多线程 67
第十一章 网络编程 73
项目阶段课程5 80
附:内部类专题(自学) 80
线程池专题(自学) 83
附3:设计模式初步专题(自学,适合初级.更深入的会在框架阶段) 84
XML技术 86
反射 92
正则表达式(自学) 93
阶段项目课程6 99
百大项目第一阶段:项目调研 99
Oracle和Mysql数据库技术 99
阶段项目课程7 113
百大项目第二阶段:数据库表设计 114
存储过程 114
JDBC技术 115
阶段项目课程8 123
HTML语言 124
CSS语言 124
阶段项目课程9 125
HTML5新标签和新功能 126
BootStrap技术 128
阶段项目课程10 128
JavaScript语言 128
jQuery技术 134
阶段项目课程 11 147
服务器端编程(Servlet技术) 147
JSP技术 154
EL和JSTL标签库 155
AJAX技术 156
阶段项目课程12 156
中级补充课程 156
阶段项目课程13 157
百大项目第三阶段:需求分析、概要和详细设计 158
Struts2 框架 159
Hibernate 框架 160
Spring 框架 162
阶段项目课程14 164
Spring MVC技术 166
MyBatis 框架 168
EasyUI技术 170
RBAC技术 170
shiro安全框架 171
阶段项目课程15 172
maven 174
Linux系统实战 174
逆向工程、分页插件 175
Nginx服务器与vsftp服务器 175
HttpClient、jsonp、dubbo 176
Redis存储系统 176
solr企业级搜索 177
Zookeeper分布式系统和服务集群搭建 180
SSO单点登录 180
阶段项目课程16 181
JFinal 敏捷开发框架 183
百大项目第四阶段:项目核心模块开发 184
自由项目和风险投资17 184
百战程序员Java1573题
班级编号: 教学质量投诉邮箱: [email protected]
本套课程体系为北京尚学堂科技集十年教学精华打造而成,并且是高端品牌“百战程序员”的主要教学体系之一(约占1/4课程,还有大数据、架构师、产品经理。4核课程让你挑战CTO职位)。“百战程序员”有“身经百战”含义,我们希望在培训期间学员就能身经百战,学习和参与各种项目,身经百战,脱胎换骨,高薪工作手到擒来。
《百战程序员Java1573题》是集北京尚学堂10年Java教学精华所成, 同时按照教学进度,从零开始步步深入,直到成为年薪20万的程序猿。按照我们目前的数据统计,能够完成1573题80%的同学,年薪应该可以达到20万左右。对于一般同学来讲,能够完成50%就足够找一份年薪10万的工作。可以说,本套题集字字千金!不,题题千金。
由于课程量较大,而且加入了很多新技术,希望同学们课上认真跟讲师互动,课下认真复习,争取毕业时拿到较高、较满意的薪水。
本套课程是尚学堂经过10年教学改版的最新课程,包含了无数老师的心血。
如果学习期间,我们的教学活动有需要改进的地方,可以跟授课讲师直接交流,或者您可以将具体意见直接投诉到北京总部邮箱:[email protected]. 我们将会在第一时间进行改进,并与您取得联系。
本套课程的教学进度是经过尚学堂多位金牌讲师合力制定,有一定的科学性。
本套课程配套视频由全国最牛的“七星团队”录制。 马士兵、高淇、裴新、邹波、李毅、胡琦光、卢俊杰、齐毅、刘凯利、夏中云、高明鑫等。每位老师都有10年以上开发和教学经验。
本套课程体系 (1.0版)已经完成,视频和其他资料我们将每周进行更新, 想加入我们一起学习,请加入QQ群:453049965或者416323638 通过申请后加入我们,广交朋友,一起学习,一起战斗。
百战程序员介绍
官网:www.itbaizhan.com
让成功只需努力,不需运气
把小白培养成CTO的黄埔军校
我们的理念:
让成功只需要努力,不需要运气!
我们的定位:
把小白培养成CTO的黄埔军校
我们的承诺:
按效果收费,保障年薪,少一万,赔一万
我们的薪水保障(我们对课程有信心到会将保底薪水合同里面,愿意承担法律责任):
第一年年薪15万(保底薪水,拒绝玩文字游戏)
第二年年薪30万(保底薪水,拒绝玩文字游戏)
第三年年薪40万(保底薪水,拒绝玩文字游戏)
为什么叫“百战程序员”?
北京尚学堂科技旗下高端品牌,十余年教学实践、项目实战,50多位企业技术总监参与研发课程,所有精华全部汇聚到“百战程序员”,致力于打造成“培养CTO的黄埔军校”。
源自成语“知己知彼,百战不殆”,广义的含义就是:做好充分准备,每次挑战都能成功。这也是完全符合我们的理念“让成功变得简单,只需要努力,不需要运气”。
“百战”也暗含“百战百胜”之意,非常吉利。
“百战”也是我们教学方案的缩写“百大项目案例实战”,整个为期3年时间,我们会准备100个项目实战案例,为大家冲击CTO岗位做好充分准备。
最后,希望所有“百战程序员”, 靠自己努力,成为改变家庭命运的有责任感的战士、奋斗的战士、不屈的战士、百战百胜的战士!
培养理念和课程体系:
2017年
覆盖专业:(Java方向)Java+大数据+架构师+产品经理
覆盖专业:(PHP方向)Java+大数据+架构师+产品经理
CTO的含义是”首席技术官”,国内一般称为“技术总监”, 一般是分管技术的副总级别,也就是公司技术一把手, 需要对公司整体的技术方案负全责, 这就需要CTO具有相当强的综合能力。
尚学堂十余年培训数万人,影响了几百万程序员,具统计只有约9.83%的程序员最终走到了CTO或类似级别的岗位,成为真正的人生赢家。 典型代表是腾讯公司股东和副总裁张志东先生。也是众多技术发烧友的“最终梦想”,也是我们“百战程序员”的梦想, 也告诉大家IT界有很多技术宅男实际上身价亿万。
(百科链接:http://baike.baidu.com/item/%E5%BC%A0%E5%BF%97%E4%B8%9C/12113)
业界公认评价
张志东很值得尊敬,一是其技术上的炉火纯青,即便是他的对手,都对这点佩服得五体投地。QQ的架构设计源于1998年,截止到2009年8月,QQ用户数从之前设计的百万级到现在的数以亿计,整个架构还在适用。 张志东值得尊敬的另一个原因是其对物质上的追求极低,在腾讯创始人们纷纷在澳洲买别墅,开游艇,高管集体团购宝马的态势下,张志东却一直开着20多万的中档车。”
(马化腾旁边的就是:腾讯另一个主要创始人,张志东)
我们设计的课程涵盖了作为CTO需要了解的绝大部分技术内容,是尚学堂十余年研发的精华所在,累计投入研发经费1200万元,里面包含了50余位CTO的技术精华,并且我们会持续更新。
我们设计为四个方向,是为了全方位综合性的培养人才,事实上,只有精通任何一个方向,熟悉其他一个方向,就足够能拿到40万以上的年薪。 各位在学习的时候,也不要期望能将多个方向全部精通。我们的理念仍然延续北京尚学堂最基本的教学理念“实战化”,希望百战程序员们“身经百战,见识各种技术、各种项目,集百家所长”, 这样更有机会成为CTO。
课程体系:(详见Java、大数据、互联网架构师、产品经理)
Java/PHP: 作为未来的CTO怎么能不熟练掌握一门开发语言呢? 这是进入行业的基础
大数据: 大数据是目前和未来都很热门的方向。课程涵盖:大数据、机器学习、云计算。
互联网架构师: 涵盖高并发、虚拟机调优、数据库优化、分布式架构等。
产品经理: 乔布斯就是最好的“产品经理”,不懂得产品设计过程如何做好“CTO”?
为何我们敢保障15万(第一年)、30万(第二年)、40万(第三年)年薪, 甚至写到合同里面?【即使你在家自学本套1370题目,掌握80%,就可以挑战20万年薪了!】 事实上,只要精通任何一个方向,熟悉其他一个方向,就足够能拿到40万以上的年薪。 定位4个方向全方位发展,让学员更安全更有保障能拿到对应薪酬,这样也让公司更安全,让“百战程序员”品牌更有分量。
看看“百战程序员”前身“大数据班”学员的就业吧,仅仅掌握了Java和大数据,第一年就个个嗷嗷叫, 冲击30万年薪了。 当然,为了安全起见,我们第一年保底薪资保守的定到15万。 以前的“双核CPU”课程就足够保障了, 那么现在的“四核CPU”课程呢? 学员们很期待,我们也很期待!
以下聊天记录为学员和老师的对话,为了不影响学员工作,一般将名字隐去。
年薪37万,这只是刚毕业第一年的学员!还有一个23K*12=27.6万年薪。注意,这只是学了Java,再学了大数据的学员,并且只是第一年。如果,将架构师和产品经理学完呢?当然,我们不主张一直再学校学习,第二年和第三年全部是平时上班,周末集训。
当然,这些是其中的优秀学员!
下面是相对普通的毕业学员,一行三人来北京学习,毕业后分布在北上广深一线大城市, 平均月薪16k,年薪为:16*12=19.2万,未加五险一金、补助和年终奖。加入的话,妥妥突破20万。
百战程序员培养时长和方式:
腾讯等大型企业对技术人员定级和相应的薪酬标准(2015年,后续年份自我脑补):
入学方式:
进入官方网址:itbaizhan.com
联系报名
自学
北京大学计算机系教授都推荐的课程,你怎么能不自学,可以自行看视频学习,也可以加入自学辅导班(收费:480元,时长4年有效)
参加入学考试(技术笔试、面试)
通过考试者,可以入学
大学毕业的报名者,请携带毕业证和身份证
大学在校生,请携带学生证和身份证
免费实训4天,双向选择
免费特训4天,能不能撑下来。能撑下来就跟,不能淘汰。
正式签订合同,开始学习
收费方式:
可0学费入学!可参与合作单位、百度金融等大型机构和银行的学习贷款,让你零学费入学,赚钱后再还学费(通过学习每个月多赚3000就相当于免费学了。很多学员学完后是每个月多赚1万)!
每年付一次,双向选择,客户决定是否续费第二年服务
开班计划(2017年,共计:6期)
JavaSE编程基础
第一章 初识Java
你学习编程的目的是什么?学习编程最快的办法是什么?
程序员的职业规划是什么?我怎么能拿到10万年薪,30万年薪,50万年薪?
一个技术点,怎么样才能算学会?需要能默写出来吗?
北京尚学堂旗下“百战程序员”的理念和定位是什么?
如何考取百战程序员,进入正式班级学习?
哪个网站会公布最新的“百战程序员”视频和资料?
说出计算机语言为什么按照第一代、第二代、第三代发展?
降低计算机语言开发难度,减少对计算机硬件的直接编程
Java有什么核心优势让其流行?
跨平台性
互联网上的电脑硬件不同,软件环境差异较大。需要一个跨平台的语言。
Java的三个版本是什么?
JavaSE: 定位在客户端,主要用于桌面应用软件的编程
JavaEE:定义在服务器端的企业版,主要用于分布式网络程序的开发
JavaME:主要应用于嵌入式系统开发,如手机和PDA的编程
Java是哪个公司发明的? 现在这家公司处境如何? 为什么?
Java是Sun公司发明的
Sun公司在2009被Oracle公司收购
因为Sun是一家极具创新能力的公司,但是没能利用Java构建一个强有力、可变现的生态系统,没打好Java这张牌
Java的跨平台是通过什么实现的?
通过在不同平台上安装相应的Java虚拟机实现的;虚拟机可以将字节码文件(class)解释成相应平台的机器语言并执行
Java语言释型还是编译型?还是两者都是?
先编译再解释
JDK、JRE、JVM的全称是?
JDK: Java Development Kit 针对Java开发员的产品
JRE: Java Runtime Environment是运行Java程序所必须的环境集合
JVM:Java Virtual Machine解释运行Java字节码文件,跨平台的核心
JDK包含JRE,这句话对吗?
对;JDK包含JRE;同时JRE包含JVM
【上机】熟悉DOS命令行方式的常用命令:dir、cd等.
DOS下,自动补齐命令的键是哪个?DOS下,想查找以前执行的命令用哪个键?
DOS下,自动补齐命令的键是哪个Tab键
DOS下,想查找以前执行的命令用上下箭头, ↑或↓键
DOS下,dir命令表示什么含义? cd 表示什么含义?
dir:查看某个目录下的子目录和文件
cd:改变当前目录
【上机】安装JDK、配置环境变量、并写出自己的第一个HelloWorld程序
需要配置Java_HOME ,path,classpath三个环境变量
public class Test{
public static void main(String args []){
System.out.println("Hello World");
}
}
为什么采用Java_HOME的方式配置环境变量较好?
便于Java_HOME路径的重用,避免由于JDK安装路径变化而修改多个环境变量;
public class 的类名必须跟文件名保持一致吗?
public class 的类名必须跟文件名保持一致
编程风格一定要:成对编程和缩进。用文字或代码说明如何实现成对编程和缩进。
public class Test{
public static void main(String args []){
System.out.println("Hello Java");
System.out.println("尚学堂");
}
}
system.out.println("hi"); ----这句代码能否顺利执行?
不能顺利执行;Java区分大小写,需要将system修改为System
一个Java源文件可以写多个class吗?编译后,会不会生成多个class文件?
一个Java源文件可以写多个class?编译后会生成多个class文件
编程时,为什么需要注释?注释的类型?
注释就是程序员为读者作的说明,是提高程序可读性的一种手段;注释同时也是调试代码时的一种手段,可以对某些不要执行的代码进行注释;
注释分为单行注释,多行注释和文档注释三种类型;
多行注释能不能嵌套使用?
多行注释不能嵌套使用
【上机】使用snagit/ FastStone Capture软件截图
【上机】使用pdf阅读器做笔记,阅读相关电子书文档
【上机】使用录屏软件Camtasia录制和转换视频
【上机】使用onenote记笔记和画图
【上机】使用亿图软件画出相关图形
阶段项目课程1
【项目】台球游戏小项目
练习目标:
- 找到敲代码的感觉
- 收获敲代码的兴趣
- 作出效果,找到自信
- 从一开始就学会调试错误
- 掌握Java代码基本结构
注意:不要求学生理解代码的语法功能,只要按照代码结构输入代码,能够经过调试实现代码的正常运行即可;
全部讲解和练习时间控制在2小时以内
项目需求:
桌球在球桌中按照一定线路和角度移动;遇到边框会自动弹回
要求:
即使看不太懂,也要照着敲如下游戏代码,至少5遍。要求所有字符和源文件一致。如果报异常,请细心看所在行和老师代码有何区别:
第二章 数据类型和运算符
常用的进制有哪些?
十进制、二进制、八进制、十六进制
如何将10进制转换为2进制数据
除2取余,逆序排列
举例:
位、字节、字符的概念及其计数范围?
位:计算机存储信息的基本单位,代表一个二进制数位,
计数范围:0或1
字节:8个连续的二进制位为一个字节,可以存放1个西文字符的编码
计数范围:-128~127
字符:单引号用来表示字符常量,例如 ‘A’,‘张’
计算范围:0-65535之间的编码
标识符的作用是什么?
用作给变量、类和方法命名
这个标识符合法吗? int aaa@bbb = 33;
不合法
标识符能不能使用汉字开头?为什么?
可以,字母的含义包括:英文、汉字等(不建议大家使用汉字来定义标识符)
Java中有没有goto语句?有没有goto关键字?
java中没有goto语句,有goto关键字
byte,short,int,long类型,分别占用几个字节?表数范围多大?
byte:1个字节 -128~127
short:2个字节 -215~215-1
int:4个字节 -231~231-1
long:8个字节 -263~263-1
整型常数默认是什么类型?
int类型
float,double分别占用几个字节?
float:4个字节
double:8个字节
如何用科学计数法表示3.14?
314E-2
浮点常量默认是什么类型?
double类型
如下写法哪些是不对的:
a. byte b = 30;
b. byte c = 500;
c. long d = 2343223;
d. float f = 3.14;
b:不对,超出了byte的范围
d:不对,缺少f,应该写为3.14f或3.14F
浮点数能用于比较吗?下面可能打印什么结果:
打印结果为: d1 == d2
float类型的数据在内存中的存储形式为科学计数法, 且有效位数为7位, 则d1为4.2343242E7, d2用科学计数法表示同样为4.2343242E7, 因此d1 == d2
字符型变量几个字节? 这种写法对不? char c = "d";
字符型变量占2个字节
写法不对,应该为char c=‘d’;
布尔型变量占用空间是一位还是一个字节?
布尔型变量占一位
这种写法好不好? if(b==true)
不好,应写为if(b)
常量的声明使用哪个关键字?
常量的声明使用的关键字是final
常量的命名规范是?
全部由大写字母组成,单词间通过下划线来界定
解释一下,驼峰原则?
当变量或函数名称需要多个英文单词组成时,首字母以小写开头,每个单词首字母大写(第一个单词除外)
使用Scanner接收键盘输入,是否一定要加import Java.util.*; ?
需要导包
也可以写为import java.util.Scanner;
类名的命名规则是? 方法名、变量名的命名规则是否一致? 常量的命名规则是?
类的命名规则:每个英文单词的首字母都大写
方法名、变量名的命名规则:第一个单词首字母小写,从第二个单词后,每个单词的首字母大写
常量的命名规则:字母全部大写
引用类型是占用几个字节?
引用数据类型占4个字节,用于存储对象的引用
算术运算符中类型提升是怎么回事? a+b返回什么类型? int a=3; long b=3;
类型提升指的是自动类型转换
a+b返回的是long类型
i++和++i的异同之处
相同:都是变量i自增1
i++与++i作为一条单独语句使用时, 没有区别
不同:i++是先使用i的值进行其他运算,然后再自增1
++i是先自增1,然后再使用i的值进行其他运算
关系运算符中,能不能这么写:"1 不能,
应该写为a>1&&a<3
逻辑运算符|、&、!、^的含义及其运算规则?
| 或: 只要有一个为true,则直接返回true
& 与: 只要有一个为false,则直接返回false
! 非: 如果为true,则返回false,如果为false,则返回true
^ 异或: 如果两个操作数相同,则返回false,如果两个操作数不同,则返回true
运算符||和|的异同之处
相同:
|| 与 | 都是逻辑运算符, 运算规则都为只要有一个为true,则直接返回true
不同:
|| 短路或 : 从左到右计算,如果符号左边的操作数为true,则不会继续计算,直接返回 true; 如果符号左边的操作数为false,则需要继续计算
| 逻辑或:操作数左右两边的操作数都需要计算,不会发生短路
|| 只是逻辑运算符
| 还可以是位运算符中的按位或符号
5*4最快的运算方式是?
位运算5<<2
这两个表达式分别返回什么结果? ((1<3)?"a":"b")+3+4, x=-2; x > 0 ? 1 : (x == 0 ? 0 : -1)
((1<3)?"a":"b")+3+4 返回结果为a34
x=-2; x > 0 ? 1 : (x == 0 ? 0 : -1) 返回结果为-1
什么情况下,加号会变成字符串连接符?
“+”号左右一个为String类型时,则变成字符连接符
4&5,4|5的结果分别是多少? 4&&5这个操作可行吗?为什么?
4&5的结果为4
4|5的结果为5
4&&5这个操作不可行,因为&&左右要求为boolean类型表达式
int能否自动转换成byte,short,char? 是否有一定条件才能转换?
不能
需要强制类型转换
long能自动转换成int吗?long能自动转换成float吗?
long可以自动转成int
long可以自动转成float
自动类型转换中,容量小和容量大指的是什么意思?
容量大小指的是不同数据类型的存储数据的范围
强制类型转换中,是否可能发生数据丢失?
可能发生数据丢失
布尔类型能否自动转换为int? 如果不能,简述理由。
不能
因为类型不匹配
下面两种写法,哪个较好:
a. 70L60243657020
b. 7060243657020L
第一种写法好;
第二种表达式的前半部分70602436570的乘积有可能会超过int的取值范围, 导致精度损失
第三章 控制语句
三种控制结构是什么?
顺序结构,选择结构,循环结构
如果if语句后面不写{},if的控制范围是否只限于第一句?
正确
Math.random()是什么意思?如果想获得15-20之间的随机数,怎么办?
产生一个0-1之间的随机数,包含0但不包含1
(int)(Math.random()*6)+15;
switch语句的功能是否完全可以使用if else if else多选择结构来代替?如果是,为什么还需要switch结构?
可以
switch一般用来做多值的判断,如果判断条件为区间,则最好使用多重if来做,如果是等值情况最好使用switch来做
switch中的表达式的结果需要是什么类型?
byte,char,short,int
jdk1.5 加入了枚举
jdk1.7加入了String
switch语句中,一个case开始执行后,什么时候结束执行这个case的语句?
遇到break结束执行这个case语句
switch语句中,default是否必须写?
不是必须写
下面代码有什么错误?
case后的表达式后面应该是“:”冒号
循环结构模拟了现实世界中的什么逻辑?
循环结构模拟了现实世界中的“重复问题“的逻辑
循环结构的四种内部结构是什么?
while(布尔表达式){
循环体;
}
do{
循环体;
}while(布尔表达式);
for(初始表达式;布尔表达式;迭代因子){
循环体;
}
foreach(数组或集合中元素的类型 迭代变量:数组或集合名){
循环体;
}
while和dowhile有什么区别?
当条件不成立时,do-while至少执行一次
什么情况下,会出现死循环?并写出一个例子来
循环条件始终成立时,则会出现死循环
while(true){
System.out.println(“helloworld”);
}
for循环相比while循环有什么优势?
语法结构比while简便,
通常用于解决循环次数固定的问题
下面代码都有什么问题:
a没有初始化
下面代码有错误吗?如果有,指出错误:
i超出了作用域的范围
循环中,break的作用是?continue的作用是?
break用于强行退出循环,不执行循环中剩余的语句
continue用于跳过本次循环, 不执行continue后的语句, 继续下一次循环
语句块能否使用外部的变量?语句块中定义的变量,外部能否使用?
语句块能使用外部的变量, 但是语句块中定义的变量外部不能使用
方法的定义中,是否必须要有返回值类型?如果确实不需返回值,使用哪个关键字声明?
返回值类型不是必须的
不需要返回值使用关键字void
方法的定义中,return是否必须?它有什么作用?
不是必须
return语句终止方法的运行并指定要返回的数据
Java中,参数的传递使用值传递还是引用传递?
值传递
方法定义中,形式参数和实际参数有什么区别?用自己的话描述。
方法定义时的参数称为形式参数,需要数据类型
方法调用时的参数称为实际参数,不需要类型,只需要值
方法定义时,使用实参还是形参?
方法定义时,使用的是形参
定义形参时,必须要写变量类型吗?
必须要写变量类型
实参类型是否必须和形参类型匹配?
必须匹配
什么是方法的重载,有什么作用?
方法重载:
[1]在同一个类中
[2]方法的名称相同
[3]参数列表不同
[4]与访问修饰符和返回值类型无关
[5]与异常无关
作用:
传递不同的参数实现相同的效果
两同三不同指的是?返回值不同构成重载吗?形参名称不同构成重载吗?
两同:同一个类中,方法名称相同
三不同:参数列表的参数的类型,个数,顺序不同
返回值不同构不能方法得载
形参名称不同构不成方法重载
递归算法中,递归头和递归体分别指什么?
递归头:什么时候不调用自己方法,即递归的结束条件
递归体:什么时候需要调用自己方法,即自己调用自己
递归算法的优点是什么?缺点是什么?
递归的优点:将问题逐渐简单化
递归的缺点:会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度 比循环慢的多。
【上机】使用递归算法完成阶乘算法
public static int jiCheng(int number){
if (number==1) {
return 1;
}else{
return numberjiCheng(number-1);
}
}
【上机】根据随机生成的的月份,打出该月份的天数.(不考虑闰年、闰月)
public class Test{
public static void main(String [] args){
int day=0;
int ran=(int)(Math.random()12)+1;
switch(ran){
case 2:
day=28;
break;
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day=31;
break;
default:
day=30;
break;
}
System.out.println(ran+”月,共”+day+”天”);
}
}
【上机】用while和for循环分别计算100以内奇数和偶数的和,并输出。
(1)求1-100以内奇数的和;
用while循环:
int i=1;
int sum=0;
while(i<=100){
sum=sum+i;
i+=2;
}
System.out.println("1-100之间所有奇数的和是"+sum);
用for循环:
int i=1;
int sum=0;
for(i=1;i<=100;i+=2){
sum=sum+i;
}
System.out.println("1-100之间所有奇数的和是"+sum);
(2)求1-100以内偶数的和(略)
【上机】用while和for循环输出1-1000之间能被5整除的数,且每行输出3个。
用while:
int i=1;
int count=0;
while(i<=1000){
if(i%5==0) {
System.out.print(i+"\t");
count++;
if(count%3==0){
System.out.println();
}
}
i++;
}
用for循环:
int i=1;
int count=0;
for(i=1;i<=1000;i++){
if(i%5==0) {
System.out.print(i+"\t");
count++;
if(count%3==0){
System.out.println();
}
}
}
【上机】打印出九九乘法表
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
System.out.print(j+”” +i+”=”+(ij)+””);
}
System.out.println();
}
【上机】编程求:∑1+∑2+……+∑100
public static int getSum(int number){
if(number==1){
return 1;
}else{
return number+getSum(number-1);
}
}
public static void main(String [] args){
int sum=0;
for(int i=1;i<=100;i++){
sum+=getSum(i);
}
System.out.println(“和为:”+sum);
}
【上机】生成0-100随机数,直到生成88为止,停止循环!
public static void main(String[] args) {
//生成1-100随机数;
int r=(int)(Math.random()100)+1;
while(r!=88){
r=(int)(Math.random()100)+1;
}
}
【上机】把100~150之间不能被3整除的数输出
for(int i=100;i<=150;i++){
if(i%3!=0){
System.out.println(i);
}
}
【上机】打印出实心1010正方形、空心1010正方形
for(int i=1;i<=10;i++){
for(int j=1;j<=10;i++){
System.out.print(“*”);
}
System.out.println();
}
【上机】打印出实心1010菱形, 空心1010菱形
//1-6行正三角
for(int i = 0; i < 6; i++){
//前空格
for(int j = 0; j < 5 - i; j++){
System.out.print("");
}
//
for(int j = 0; j < 2 * i + 1; j++){
System.out.print("");
}
//后空格
for(int j = 0; j < 5 - i; j++){
System.out.print("");
}
System.out.println();
}
//7-11行倒三角
for(int i = 0; i < 5; i++){
//前空格
for(int j = 0; j < i + 1; j++){
System.out.print("");
}
//
for(int j = 0; j < 9 - 2 * i; j++){
System.out.print("");
}
//后空格
for(int j = 0; j < i + 1; j++){
System.out.print("");
}
System.out.println();
}
【上机】将如上所有上机相关算法的作业,封装成方法,便于重用。
第四章 数组
数组的类型可以为任意类型吗?
可以是任意类型
数组中的元素的类型必须是相同的吗? 数组中的元素是有序的吗?
数组中元素的类型必须是相同的
数组中元素是有序的, 索引的顺序
数组的长度可变不? 数组的长度使用哪个属性?
数组一旦声明其长度不能更改
数组的长度属性是length
数组元素下标(或索引)的范围是?
范围是0-数组名.length-1
数组也是引用类型吗? 数组也是对象,这句话对吗?
数组是引用数据类型
数组也是对象这句话正确
数组中的元素就像对象中的成员变量一样,初始化方式也一样。这句话对吗?
正确
【上机】数组的三种初始化方式是什么? 并测试练习相关代码
静态初始化
int [] a={1,2,3};
动态初始化
int [] a=new int[2];
a[0]=1;
a[1]=2;
默认初始化
int [] a=new int[2];//0,0
数组的静态初始化代码,下面代码有没有不合理的地方:
有,new Dog(“小强”,2)后的逗号应去掉
完成如下代码:
下面的数组定义哪些是正确的?
CDE是正确的
请在下面语句中找出一个正确的。
A. int arr1[2][3];
B. int[][] a2 = new int[2][];
C. int[][] arr2=new int [][4];
D. int arr3[][4]= new int [3][4];
B正确
【上机】定义一个长度为10 的一维字符串数组,在每一个元素存放一个单词;然后运行时从命令行输入一个单词,程序判断数组是否包含有这个单词,包含这个 单词就打印出“Yes”,不包含就打印出“No” 。
public class Test{
public static boolean isFind(String [] arr,String word){
boolean isFlag=false;
for(int i=0;i
isFlag=true;
break;
}
}
return isFlag;
}
public static void main(String [] args){
String[] arr={“hello”,”world”,”java”,”html”,”oracle”,
”apple”,”orange”,”banana”,”red”,”green”};
System.out.println(isFind(arr,args[0])?”Yes”:”No”);
}
}
冒泡排序的基本思路
1.整个数列分成两部分:前面是无序数列,后面是有序数列
2.初始状态下,整个数列都是无序的,有序数列是空
3.如果一个数列有n个元素,则至多需要n-1趟循环才能保证数列有序
4.每一趟循环可以让无序数列中最大数排到最后,(也就是说有序数列的元素个数增加1)
5.每一趟循环都从数列的第一个元素开始进行比较,依次比较相邻的两个元素,比较到无序数列的末尾即可(而不是数列的末尾)
6.如果前一个大于后一个,交换
7.根据是否发生交换判断数组是否已经有序
使用冒泡排序完成数组元素的排序
int [] array={34,23,4,55,34,53};
for(int i=0;i
for(int j=0;j
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
Flag = false;
}
}
if(flag){
break;
}
}
可变参数的作用及其用法
作用:适用于参数个数不确定、类型确定的情况,java把可变参数当做数组处理
用法:
只能出现在参数列表的最后
…位于变量类型和变量名之间,前后有无空格都可以
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数
如何给main方法传递实参
通过命令行参数给main方法传递实参
【上机】用二重循环求出二维数组b所有元素的和:
int[][] b={{11},{21,22},{31,32,33}}
int sum=0;
for(int i=0;i
}
}
System.out.println(“和为:”+sum);
eclipse可以开发Java,可以开发c++吗?
可以
eclilpse中的debug模式有什么好处?
修正语法错误和逻辑错误的过程,保证程序的正确性
eclipse中运行一个Java程序,如何操作?
单击右键选择run As ,再选择java Application
eclipse需要安装吗? 使用eclispe需要安装JDK吗?
不需要
【上机】熟悉eclipse开发环境,建立一个Java项目,并运行一个类
【上机】熟悉eclipse的调试环境(debug),建立一个Java项目,并使用debug 进行调试,测试程序每步执行情况。
假如我找不到package explore视图了,怎么样才能让他出现?
菜单栏WindowShow Viewpackage explore
阶段项目课程2
【项目】福彩双色球项目
练习目标
- 掌握数据类型和运算符
- 掌握流程控制
- 掌握数组
- 掌握方法的定义和调用
- 提高代码调试能力
全部讲解和练习时间控制在4小时以内
项目需求
双色球投注区分为红色球号码区和蓝色球号码区,
红色球号码区由1-33共33个号码组成,蓝色球号码区由1-16共16个号码组成。
投注时选择6个红球号码和1个蓝球号码组成一注进行单式投注,每注金额2元。
中奖规则同福彩双色球规则;
显示中奖结果的同时显示您一共下注人民币??元,累计中奖人民币??元
扩展:
按照自己的思路和老师的代码模板,设计一个小的作业项目。
将上一个作业作业录制成自己的教学视频
第五章 面向对象
简述面向对象和面向过程的区别和联系?
两者都是软件开发思想,先有面向过程,后有面向对象。在大型项目中,针对面向过程的不足推出了面向对象开发思想。
比喻
蒋介石和毛泽东分别是面向过程和面向对象的杰出代表,这样充分说明,在解决复制问题时,面向对象有更大的优越性。
面向过程是蛋炒饭,面向对象是盖浇饭。盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是“可维护性”比较好,“饭” 和“菜”的耦合度比较低。
区别
编程思路不同: 面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。
封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。
面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。
对象和类的关系是?
类是抽象的
对象是具体的,是类抽象概念的实物表达
栈的特点是?存放什么内容?
栈的特点:先进后出
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
堆得特点是?存放什么内容?
堆内存的特点:
堆内存有内存地址,都是将内存的地址赋值给引用变量
堆内存变量无用后由垃圾回收机制不定时回收
堆内存会自动初始化
堆内存存放引用数据类,及new出来的都在堆内存里面
【上机】画出如下程序的内存结构(课堂上的代码):
局部变量、成员变量、静态变量分别怎么声明?
局部变量:在方法或代码块中声明的变量称为局部变量
成员变量:在类中声明的变量称为成员变量
静态变量:使用static修饰的成员变量称为静态变量
局部变量使用之前,必须要手动初始化吗?
局部变量在使用之前,必须要手动初始化
如果不手动指定成员变量的值,系统将会自动初始化。那么初始化的规则是?
整型初始化为0
浮点型初始化为 0.0
引用数据类型初始化为null
boolean类型初始化为false
char类型的初始化为\u0000
成员变量从属于谁? 静态变量又叫什么以及从属于谁? 局部变量从属于谁?
成员变量从属于对象
静态变量又叫类变量从属于类
局部变量从属于方法或代码块
构造方法的作用是两个:一个构造类的对象,另一个作用是初始化对象的属性。这 种说法对不?
对
构造方法的名称必须保持跟类名一致吗?
必须与类名一致
构造方法有没有返回值?详细用文字描述返回值问题。
构造方法没有返顺值,也不可以写void
构造方法如何被调用?
构造方法在创建对象时被调用,使用关键字new
构造方法中能不能有return语句?
构造方法中不能使用return语句
系统一定会给我们添加无参数的构造方法吗? 请详细解释。
如果手动编写了构造方法之后,系统就不会添加无参构造方法了
下面的代码有什么问题:
当局部变量名称与成员变量名称相同时,使用this代表成员变量,代码应改为
computer(int price, int type, String brand){
this.price=price;
this.type=type;
this.brand=brand;
}
【上机】设计一个类代表二维空间的一个点
public class Point{
private int x;
private int y;
public void setX(int x){
this.x=x;
}
public int getX(){
return x;
}
public void setY(int y){
this.y=y;
}
public int getY(){
return y;
}
public Point(){
}
public Point(int x,int y){
this.x=x;
this.y=y;
}
}
【上机】设计一个类代表二维空间的一个圆。要求两个成员变量。一个是圆心,一 个是半径提供计算面积的方法。
public class Cricle{
private int r;
private Point point;
public void setR(int r){
this.r=r;
}
public int getR(){
return r;
}
public void setPoint(Point point){
this.point=point;
}
pubic Point getPoint(){
return point;
}
public Cricle(){
}
public Cricle(int r,Point point){
this.r=r;
this.point=point;
}
public double area(){
return Math.PI*Math.pow(r,2);
}
}
【上机】为上述Cricle类添加一个方法,计算一个点(Point对象)是否在圆(Cricle 对象)内,并写程序验证
//在Cricle类中加入方法
public class Cricle{
…..
public boolean isFlag(Point p){
if(Math.pow(x-p.getX())+Math.pow(y-getY())<=Math.pow(r,2)){
return true;
}
}
return false;
}
public class Test{
public static void main(String [] args){
Point p=new Point(3,3);//圆心
Cricle c=new Cricle(5,p);
System.out.println(c.isFlag(new Point(5,5))?”在圆内”:”不在圆内”);
}
}
构造方法能不能重载?
构造方法可以重载
this在普通方法中,指的是哪个对象?在构造方法中,指的是?
this在普通方法中总是指向调用该方法的对象
this在构造方法中总是指向正要初始化的对象
static变量在内存中放置在哪个区? static变量和方法为什么被称为类变量和类方 法?可以被该类所有对象共享吗?
static变量存在数据区
static变量和方法归类所有,使用类名去调用
可以被该类的所有对象所共享
静态初始化块和main方法哪个先被执行?
静态初始化块先执行
一个构造方法调用另一个构造方法怎么调用? this(),这样的调用方式必须位于第 一句吗?
this()调用本类的无参构造方法
this(实参列表)调用本类的带参构造方法
super()调用直接父类的无参构造方法
super(实参列表)调用直接父类的带参构造方法
this()调用必须位于构造方法的第一句
package的两个作用是什么?
解决类之间的重名问题
为了便于管理类:合适的类位于合适的包
增加package以后,我们在DOS下编译怎么做?
javac -d . Test.java
import是用于导入包还是导入类?
import是用于导入其它包中的类
import Java.util.*; 会不会降低程序运行速度?为什么?
不会降低程序的运行速度
因为是导入该包下的所有的类,会降低编译速度
import static 静态导入的作用是导入类还是导入类的静态属性和静态方法
导入类的静态属性和静态方法
如果同时导入:Java.util.Date; Java.sql.Date; 在程序中怎么区分它们?
只能用包名+类名来显示调用相关类
java.util.Date date=new java.util.Date();
【上机】 完成this、static、package、import的测试代码
package cn.sxt.pro
import java.util.Scanner;
public class Test{
public static int age;
private String name;
public void setName(String name){
this.name=name;
}
public static void show(){
}
public static void main(String [] args){
System.out.println(Test.age);
System.out.println(Test.show());
}
}
Javadoc注释怎么写?
/**开头
*/结束
Java项目的API文档如何生成?请将步骤写出。
javadoc 源文件名.java;
面向对象中的封装,追求的是“高内聚,低耦合”。解释一下,内聚什么?什么叫 耦合?
内聚:程序内的各个模块之间的关系紧密程度
耦合:外部程序(子程序)之间的关系紧密程度
封装的几个关键字:private,default,protected,public的含义。
代表的是访问权限
private:私有的,只能本类访问
default:默认的,本类,子类,本包中的其它类都可以访问
protected:受保护的,本类,本包及其它包中的子类可以访问
public:公共的,本类,子类,本包及其它中的类都可以访问
一般属性是否要设置为private?
是, 属性就不能被赋值上任何非法的值了
如果属性设置为private,如何让外部访问该属性?
编写公有的取值的get方法
提供getter、setter方法的操作,eclipse中如何实现?
菜单栏SourceGenerate getters and setters
对于boolean类型的属性,提供的getter方法是:getXXX或是isXXX?
isXXX;
Javabean就是只包含属性和相关getter、setter方法,不包含业务逻辑处理的 类,这种说法对吗?
不对
Javabean既可以封装数据同时也可以封装业务逻辑
继承的好处是什么?
好处一:继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象
好处二:为了提高代码的复用性
Java中有多继承吗?C++中有多继承吗? 单继承相比多继承优势在什么地方?
java中只有单继承
C++中有多继承
使用单继承有利于系统的维护,使得类与类之间的关系简单
【上机】模仿课堂上动物世界的例子,我们自己写个例子。
class Person{
}
class Teacher extends Person{
}
Java的继承使用哪个关键字实现?
extends
定义某个类时,如果没有使用extends,那么继承了哪个类?
如果没有使用extends,那么继承了Object类
Java中,有没有多继承? 请说明,Java为什么取消了多继承?
java中没有多继承
使用单继承有利于系统的维护,使得类与类之间的关系简单
重写(override)指的是什么?
指的是子类对父类中方法的重写
假如父类有main方法,子类能不能继承?
不能
Object是所有类的根类吗?是所有类的直接父类吗?
Object是所有类的根类
不是所有类的直接父类
在哪里查看Object类的源代码?
jdk安装目录中的src压缩包中可以查看源码
Object类中的toString方法能否被子类重写?请做测试。
能
【上机】完成继承、Object相关的测试代码
super指的是什么?
super指的是直接父类
构造方法中,第一个话总是super吗?
也可以是this()
叙述一下,有继承结构时,构造方法的调用顺序?
继承条件下构造方法的调用规则如下:
如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的。
如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。
如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则。
特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。
重写中,子类的返回值类型可不可以跟父类不完全一致?说出你的理由。
可以
子类的返回值可以与父类相同,也可以是父类方法返回值的子类
如何判断两个对象内容是否相同?重写equals()有什么要求?
判断两个对象的内容是否相同,需要重写Object类的equals方法
举一个现实的例子,说明多态。
我第一次去见丈母娘。还没见的时候,我女朋友已经把我的情况介绍给丈母娘了,说我“长得像港台明星”。见面以后丈母娘一看,哇,原来是像曾志伟。当场晕倒。
多态的三个必要条件是什么?
继承
方法重写
父类引用指向子类对象
什么是向上转型?什么是向下转型?
向上转型:父类引用指向子类对象
向下转型:将父类引用转成真实的子类对象
多态的常用使用场合有哪些?
使用父类做方法的形参,实参可以是该父类的任意子类类型
使用父类做方法的返回值类型,返回值可以改父类的任意子类对象
Java的方法绑定采用动态绑定还是静态绑定?
静态方法,构造器,private方法,用关键字super调用的方法是静态绑定
通过对象调用的方法,采用动态绑定
final修饰变量、方法、类分别表示什么含义?
final修饰的变量不可改变,一旦赋了初值,就不能被重新赋值,称为常量
final 修饰的方法不能被子类重写
final修饰的类不能有子类
final修饰的方法能不能被重载?能不能被重写?
final修饰的方法可以重载
final修饰的方法不能重写
String类能不能被继承?为什么?
String类不能被继承
因为String类是使用final修饰的类
包含抽象方法的类是抽象类吗? 抽象类一定包含抽象方法吗?
包含抽象方法的类是抽象类
抽象类中不一定含有抽象方法
抽象类中能不能有普通方法?能不能定义构造方法?
抽象类中可以有普通方法
抽象类中可以定义构造方法
抽象类能不能被new出来?即抽象类的构造方法能不能被调用?
抽象类不能被new出来
抽象类的构造方法被子类调用
接口中只能定义常量和抽象方法吗?
JDK1.7之前,接口中只能定义静态常量和公共的抽象方法
JDK1.8中,接口中可以定义静态方法
接口描述了现实世界中什么逻辑?
接口描述了现实世界是“如果你是…则必须能..”的思想
如果你是天使,则必须能飞;如果你是汽车,则必须能跑
接口中的常量一定是public static final吗?抽象方法一定是public abstract 吗?
是的
接口中能不能定义普通变量,普通方法?从设计接口的角度说明为什么这么做?
接口中不能定义普通变量,也不能定义普通方法
因为接口就是一种规范,定义一种规则
接口能不能被new?
接口不能被new
接口中有没有多继承?
接口中有多继承
一个类能不能实现多个接口?
一个类能够实现多个接口
【上机】完成抽象类、接口的语法测试代码
public interface TakePhoto {
}
abstract class Phone{
}
class MoblePhone extends Phone implements TakePhoto{
}
class Test{
public static void main(String[] args) {
MobilePhone mp=new MobilePhone();
}
}
【上机】使用接口,定义电子产品系统(智能手机、MP3、智能手表)。
public interface Electronic {
}
class MobilePhone implements Electronic{
}
class Mp3 implements Electronic{
}
class Watch implements Electronic{
}
如何对一个数组的多个对象按照不同的依据进行排序;
对象实现Comparable接口
或者定义比较规则的类实现Comparator接口
模拟实现Comparable和Comparator接口;
实现Comparable接口
public class Student implements Comparable
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Student o) {
return this.age-o.getAge();
}
}
实现Comparator接口
class AgeComparator implements Comparator
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
}
GC指的是什么?写出英文全称。垃圾回收机制中,程序员能不能调用垃圾回收器?
GC:是指垃圾回收
英文:garbage collection
程序员无权调用垃圾回收器
System.gc()指的是什么意思?
运行垃圾回收器
finalize方法可以用来做什么?
在垃圾收集器将对象从内存中清除出去前,做必要的清理工作
通过两个事例描述C++,Java不同的内存回收机制。
很久很久以前,每家每户“自扫门前雪”,自己收垃圾。
现在,环保局的垃圾车自动收垃圾。
通过,这些例子类比Java和C++不同的回收机制及特点。
C++需要程序员手动编写垃圾回收的代码,如果程序员忘了那么就容易造成内存 溢出等问题
java无需手动编写,jvm的垃圾回收机制会自动进行垃圾回收,减轻了程序员的 工作,也避免由于程序员忘记而造成的各种内存溢出等问题
第六章 异常机制
Java中,处理异常的两大步是?
捕获异常
声明异常
如果catch两个异常,一个是父类,一个是子类。这两个异常的catch顺序如何 确定?
子类异常在前父类异常在后
finally里面一般放置什么代码?
无论是否发生异常,都必须要执行的语句放到finally中, 比如数据库连接的关闭、IO流的关闭、socket连接的关闭等物理连接的关闭
Error和Exception的区别和联系
联系:Error与Exception都继承自Throwable类
区别:
Exception:
[1]可以是可被控制(checked)或不可控制的(unchecked)
[2]表示一个由程序员导致的错误
[3]应该在应用程序级被处理
Error:
[1]总是不可控制的(unchecked)
[2]经常用来用于表示系统错误或低层资源的错误
[3]如果可能的话,应该在系统级被捕捉
Throwable是一个类还是接口?
Throwwable是一个类
如果碰到NullPointerException,我们一般应该如何查错?如何做处理?
如果碰能NullPointerException异常,我们应该使用debug进行调试
使用try-catch-finally进行异常捕获处理
【上机】完成课堂测试异常的代码
【上机】eclipse中,增加try-catch块的操作是怎么做的?
Alt+Shift+Z
【上机】自定义一个自己的异常类
public class SexException extends Exception {
public SexException() {
super();
}
public SexException(String message) {
super(message);
}
}
方法重写时,子类声明异常能否超出父类的范围?
子类声明异常不能超出父类的范围
[1]父类没有声明异常,子类也不能
[2]不可抛出原有方法抛出异常类的父类或上层类
[3]抛出的异常类型的数目不可以比原有的方法抛出的还多(不是指个数)
【上机】下面的代码,有什么问题? 解释原因
子类重写时,不可抛出原有方法抛出异常的父类或上层类
说出你现在接触的几个异常?尽量多写。
ArithmeticException
NullPointerException
ClassCaseException
ArrayIndexOutOfBoundsException
NumberFormatException
阶段项目课程3
【项目】太阳系项目
练习目标:
- 类和对象
- final常量
- 构造方法及其重载
- this和super关键字的使用
- 方法重写
- 类的三大特征:封装、继承、多态
- 作出效果,找到自信
注意:不要求学生对AWT编程的内容有详细认识,重点是关于太阳系星球的面向 对象设计和开发;全部讲解和练习时间控制在4小时以内 。
要求:
太阳系中八大行星围绕太阳按照不同的速度转动;月亮围绕地球转动。
根据老师课程讲解,完成太阳系项目小游戏。
扩展:
按照自己的思路和老师的代码模板,设计一个小的作业项目。
将上一个作业作业录制成自己的教学视频
第七章 常用类
为什么需要包装类?包装类的作用是?
因为java语言是面向对象的语言,但是java中的基本数据类型却不是面向对象的,而在实际的使用中经常需要将基本数据转化成对象,便于操作。比如说在集合中存储数据时,只能存储对象
作用:
[1]作为和基本数据类型对应的类类型存在,方便涉及到对象的操作
[2]包含每种基本数据类型相关的属性以及相关的操作方法
将字符串"123"转化成基本类型数字的方式有哪些?
通过Integer类的静态方法来转换
Integer.parseInt(“123”);
自动装箱和自动拆箱指的是?举例说明。
自动装箱和自动拆箱指的是将基本数据类型和包装类进行自动的互相转换
【上机】完成老师课堂上Integer的测试,并自己写Double类的测试代码
public class TestDouble {
public static void main(String[] args) {
Double int1 = new Double(10);
Double int2 = Double.valueOf(20);
double a = int1.doubleValue();
Double int3 = Double.parseDouble("334");
Double int4 = new Double("999");
String str1 = int3.toString();
}
}
为什么String类被称为不可变字符序列?从String类的源代码分析,给出解释。
字符串是常量,它们的值在创建之后不能更改,String对象是不可变的,所以可以共享
String类的底层结构是char类型的数组value,而这个数组使用final进行修饰
【上机】String类的equals方法跟Object的equals方法什么关系? 并详细阅 读String类的equals方法源代码,分析它的内部流程。
String类的equals方法重写了Object类的equals方法,用于比较两个String对象的内容是否相同
String类的equals方法的源码分析:
如果两个String对象的内存地址(引用)相同,那么return true
如果两个String对象的内存地址(引用)不相同,那么进行类型判断,如果不是String类型,那么直接返回false,如果是String类型则进行向下类型转换,转换成String类型,然后变改char类型数组,比较两个数组对应位置上的内容是否相同,如果相同返回true,如果不同返回false
String类的trim()方法是什么作用?
返回字符串的副本,去掉字符串前后的空格
"hamburger".substring(4, 8) 返回的结果是?
urge
【上机】分析下面代码的结果,并画出内存结构图,针对每个打印的结果给出文字 解释。
System.out.println(s==ss);结果为true
System.out.println(s3==s4);结果为true
System.out.println(s4==s5);结果为false
System.out.println(s4.equals(s5));结果为true
【上机】练习String类的常用方法
字符串的长度:
System.out.println(“hello”.length());
去掉字符串前后的空格:
System.out.println(“ hello world ”.trim());
截取子字符串:
System.out.println(“helloworld”.substring(0,4));
StringBuffer和StringBuilder的联系是?区别是?
联系:
StringBuffer和StringBuilder都是可变字符序列,底层数组结构都是char类型的数组
区别:
StringBuffer:jdk1.0版,线程安全,但是效率低
StringBuilder:jdk1.5版,线程不安全,但是效率高
如下的代码会造成什么后果?运行期间会产生多少个对象? 使用StringBuilder 修改这段代码。
会导致大量副本字符串对象存留在内存中,降低效率
运行期间会产生10001个对象
StringBuffer sb=new StringBuffer();
for(int i=0;i<10000;i++){
sb.append(i);
}
计算机中的时间是如何表示的?
获取从1970-1-1 0:0:0到当前时间所经历的毫秒数,然后转换为日期或者时间
System.currentTimeMillis()表示什么意思?
返回以毫秒为单位的当前时间
Date d = new Date()表示的是当前时间吗?
是,精确到毫秒
【上机】我们使用SimpleDateFormat类来实现时间跟字符串的转化。常用那两 个方法?并写出代码,举例说明
//字符串转日期
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
sdf.parse("1990-3-3");
//日期转字符串
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
sdf.format(new Date());
将1990年3月3日通过Calendar来表示,并得出这天是该年的第几天?将该日 期增加35天,是哪一天?使用代码来说明。
public static void main(String[] args) throws ParseException {
Calendar c=new GregorianCalendar();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
c.setTime(sdf.parse("1990-3-3"));
System.out.println( c.get(Calendar.DAY_OF_YEAR));
c.add(Calendar.DATE, 35);
System.out.println(c.get(Calendar.YEAR)+"年"
+(c.get(Calendar.MONTH)+1)+"月"+c.get(Calendar.DATE));
}
【上机】写代码测试Date/SimpleDateFormat/Calendar的用法。
//Date的用法
public static void main(String[] args) {
Date date1 = new Date();
System.out.println(date1.toString());
}
//SimpleDateFormat的用法
SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String daytime = s1.format(new Date());
//Calendar的用法
GregorianCalendar calendar2 = new GregorianCalendar();
calendar2.set(Calendar.YEAR, 2009);
【上机】模仿老师的写法,完成可视化日历程序的开发。
public class AppMain {
public static void main(String[] args) throws ParseException {
System.out.println("请输入日期(格式为:2010-3-3):");
Scanner scanner = new Scanner(System.in);
String dateString =scanner.nextLine();
System.out.println("您刚刚输入的日期是:"+dateString);
String[] str = dateString.split("-");
int year = Integer.parseInt(str[0]);
int month = new Integer(str[1]);
int day = new Integer(str[2]);
Calendar c = new GregorianCalendar(year,month-1, day);
c.set(Calendar.DATE, 1);
//week:1-7 日一二三四五六
int dow = c.get(Calendar.DAY_OF_WEEK);
System.out.println("日\t一\t二\t三\t四\t五\t六");
for(int i=0;i
}
int maxDate = c.getActualMaximum(Calendar.DATE);
for(int i=1;i<=maxDate;i++){
StringBuilder sBuilder = new StringBuilder();
if(c.get(Calendar.DATE)==day){
sBuilder.append(c.get(Calendar.DATE)+"*\t");
}else{
sBuilder.append(c.get(Calendar.DATE)+"\t");
}
System.out.print(sBuilder);
if(c.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY){
System.out.print("\n");
}
c.add(Calendar.DATE, 1);
}
}
File类能代表一个目录吗?
能
File类的方法mkdir跟mkdirs,有什么区别?
mkdir:只能在已经存的目录中创建文件夹
mkdirs:可以在不存的目录中创建文件夹
使用File类模拟实现DOS的dir和dir/s命令
public static void main(String[] args) {
File file = new File("e:/教学1");
showTree(file, 1);
}
public static void showTree(File file, int level){
File[] files = file.listFiles();
for (File f : files) {
for(int i = 0; i < level; i++){
System.out.print("-");
}
if (f.isDirectory()) {
System.out.println(f.getName());
showTree(f, level+1);
}else{
System.out.println(f.getName());
}
}
}
【上机】使用递归算法,根据老师的树状结构代码,完整展示一个目录树
import java.io.File;
public class FileTree {
public static void main(String[] args) {
File f = new File("d:/1005班");
printFile(f, 0);
}
static void printFile(File file,int level){
for (int i = 0; i < level; i++) {
System.out.print("-");
}
System.out.println(file.getName());
if(file.isDirectory()){
File[] files = file.listFiles();
for (File temp : files) {
printFile(temp, level+1);
}
}
}
}
什么时候使用枚举? 枚举的定义是什么?
当需要定义一组常量时,使用枚举类型
枚举的定义:
只能够取特定值中的一个
使用enum关键字
所有的枚举类型隐性地继承自java.lang.Enum
【上机】手动定义一个枚举,表示十二个月的英文月份。
public enum Month {
JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMB ER,OCTOBER,NOVEMBER,DECEMBER
}
【上机】switch语句中的表达式结果可以是枚举吗? 模仿课堂代码,写一个 例子说明。
public static String testEnum(Month m){
String str=null;
switch (m) {
case JANUARY:
str="一月";
break;
case FEBRUARY:
str="二月";
break;
default:
break;
}
return str;
}
第八章 容器
容器指的是“可以容纳其他对象的对象”,这种说法对吗?
对。
Collection/Set/List的联系跟区别?
(1)Collection是Java集合顶级接口,存储一组不唯一,无序的对象;
(2)List接口和Set接口是Collections接口有两个子接口;
(3)List 接口存储一组不唯一,有序(插入顺序)的对象;
Set 接口存储一组唯一,无序的对象;
(4) Collection,List,Set的架构关系图:
Set和List的特点跟区别?
List:
是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引来访问List中的无素,这类似于Java的数组。
凡是可以操作索引的方法都是List接口特有方法。
Set:
接口存储一组唯一,无序的对象(存入和取出的顺序不一定一致)。
操作数据的方法与List类似,Set接口不存在与索引相关的方法。
【上机】练习Collection接口中常用的方法
add(Object obj):添加,存储的是对象的引用;
size():容器中元素的实际个数;
remove(Object obj):删除一个元素;
removeAll(Collection c):删除与集合c中的元素相同的元素;
retainAll(Collection c): 只保留当前集合(调用此方法的集合)与集合c(此方法的参数)中相同的元素;
contains(Object obj):判断集合中是否存在元素obj;
isEmpty():判断集合是否为空;
Iterator():生成此集合的迭代器;
【上机】下面的代码,效果一致吗? 分析说明之。
想取两个容器中元素的交集,使用哪个方法?
retainAll(Collection c): 只保留当前集合(调用此方法的集合)与集合c(此方法的参数)中相同的元素。
说明isEmpty的作用,并说明下面代码有问题吗?
isEmpty():判断集合是否为空,也就是集合中实际元素个数是否为0,由此得知调用此方法时集合是存在的(如果集合都不存在,也就谈不上为空与否了)。要区分集合为空和集合不存在的含义是不同的。
下列代码Collection c = null,c没有指向任何集合,即集合并不真实存在,调用isEmpty()方法会出现空指针异常。
我想定义一个数组。该数组既可以放:Dog对象、也可以放Cat对象、还可以放 Integer对象,怎么定义?
代码示例:
Object[] objArr=new Object[5];
objArr[0]=56;
objArr[1]=123;
objArr[2]="Hello world";
objArr[3]=newDog();
objArr[4]=newCat();
List接口中增加了一些与顺序相关的操作方法,下面两个方法的作用是什么?
add(int index, E element) :把元素element添加到索引为index的位置;
get(int index):得到索引为index的元素。
ArrayList底层使用什么来实现的? LinkedList是用什么实现的?
见下题。
说出ArrayLIst、LinkedList、Vector的区别。
ArrayLIst、LinkedList两者都实现了List接口,都具有List中元素有序、不唯一的特点。
ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素的效率比较高;
LinkedList采用链表存储方式。插入、删除元素时效率比较高
Vector和ArrayList的区别联系:见294题。
我有一些数据,需要频繁的查询,插入和删除操作非常少,并且没有线程之间的共 享,使用List下面的哪个实现类好一些?
ArrayList。ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素的效率比较高。
【上机】针对List中新增的有关顺序的方法,每个都进行测试。并且使用debug 来帮助我们理解程序运行。
add(int index, Object obj):在指定索引位置(index)添加元素obj;
addAll(int index,Collections c):在指定索引位置(index)添加集合c中所有元素;
remove(int index):删除索引位置为index的元素;
set(int index, Object obj):使用元素obj替代指定索引位置上的元素;
get(int index):获取指定索引位置上的元素;
subList(int beginIndex,int endIndex):得到个List对象包含指定索引区间里元素。
定义Computer类,使用价格排序。(使用Comparable接口)
定义Computer类,实现Comparable接口:
publicclass Computer implementsComparable {
privatedouble price;//私有属性;
//构造方法;
public Computer(double price) {
super();
this.price = price;
}
//实现Comparable接口中的compareTo方法;
@Override
publicint compareTo(Object o) {
Computer c=(Computer)o;
if(this.price>c.price){
return 1;
}elseif(this.price
//重写toString()方法;
@Override
public String toString() {
return"Computer [price=" + price + "]";
}
}
加入TreeSet;
import java.util.Iterator;
import java.util.TreeSet;
publicclass Test {
publicstaticvoid main(String[] args) {
//创建TreeSet;
TreeSet
//创建Computer对象;
Computer computer1=new Computer(3000);
Computer computer2=new Computer(2650);
Computer computer3=new Computer(5878.8);
Computer computer4=new Computer(6000.78);
//将Computer对象加入到treeSet中;
treeSet.add(computer1);
treeSet.add(computer2);
treeSet.add(computer3);
treeSet.add(computer4);
//为treeSet创建迭代器;
Iterator it=treeSet.iterator();
//遍历treeSet
while(it.hasNext()){
System.out.println(it.next());
}
}
}
结果:实现价格排序;
Computer [price=2650.0]
Computer [price=3000.0]
Computer [price=5878.8]
Computer [price=6000.78]
equals返回true,hashcode一定相等吗?
是的。
HashSet和TreeSet的区别
HashSet:
存储结构:采用Hashtable哈希表存储结构
优缺点:
优点:添加速度快,查询速度快,删除速度快
缺点:无序
TreeSet
存储结构: 采用二叉树的存储结构
(2) 优缺点:
优点:有序(排序后的升序)查询速度比List快
(按照内容查询)
缺点:查询速度没有HashSet快
使用HashSet存储自定义对象,为什么需要重写hashCode()和equals()?
HashSet存储用的哈希表结构,哈希表需要用到hashCode()和equals()方法:
hashCode()产生hash值以计算内存位置;
当hash值相同时要调用equals()方法进行比较。
如果不重写,调用的是Object的hashcode,而Object的hashCode实际上是地址。系统类已经覆盖了hashCode方法。
所以HashSet存储自定义对象的化要重写hashCode()和equals()方法,目的是告诉程序去除重复元素的策略。
使用TreeSet存储多个学生数据,实现按照不同属性值进行排序?
创建一个Student类, 实现Comparable接口;
publicclass Student implementsComparable {
//私有属性;
privateint id;
privateint score;
//getter和setter方法;
publicint getScore() {
return score;
}
publicvoid setScore(int score) {
this.score = score;
}
publicint getId() {
return id;
}
publicvoid setId(int id) {
this.id = id;
}
//构造方法;
public Student(){
}
public Student(int id, int score) {
super();
this.id = id;
this.score = score;
}
@Override
public String toString() {
return"Person [id=" + id + ", score=" + score + "]";
}
//实现compareTo方法,这里是用id比较;
publicint compareTo(Object obj){
Student other=(Student)obj;
int result=this.id-other.id;
return result;
}
}
加入TreeSet;
publicclass Test2 {
publicstaticvoid main(String[] args) {
/*
参看下面创建TreeSet时有两种方法:
代码1:使用无参构造方法TreeSet(),当 Student对象添加进去后,排序时的比较策略用的是Student内部实现的compareTo方法(内部比较器,此例中按照学生id排序)。
代码2:使用有参构造方法new TreeSet(scoreComp);那么参数scoreComp是什么呢?它表示的是一个外部比较器的对象。在什么情形下使用呢?当用TreeSet实现排序时,我们不想用Student的内部比较器(也就是说不想用id排序),想用学生score排序?那怎么办呢?有同学说,把内部比较器改一下呗,改成用score排序的。但改来改去是不是不够灵活呢?我们有另外一种方法。还记得外部比较器吗?Student的内部比较器我们可以不改,再为Student类定义一个外部比较器(见以下代码中“定义外部比较器”的部分),定义外部比较器要实现Comparator接口中的compare(Object obj1,Object obj2)(如果忘记了就往前翻翻吧☺),在这个方法中实现用分数(score)比较。
以此类推,如果你想用其它属性比较(如年龄,姓名等),可以继续定义相应的外部比较器,使用方法参见代码2.
*/
/*
代码1:
Set treeSet=new TreeSet();
*/
/*
代码2:
ScoreComp scoreComp=new ScoreComp();//定义一个外部比较器的对象;
Set treeSet=new TreeSet(scoreComp);//把外部比较器对象作为TreeSet构造方法的参数;
*/
Student p1=new Student(1,78);
Student p2=new Student(2,67);
Student p3=new Student(3,96);
Student p4=new Student(4,87);
treeSet.add(p3);
treeSet.add(p4);
treeSet.add(p1);
treeSet.add(p2);
Iterator it=treeSet.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
//定义外部比较器;
class ScoreComp implementsComparator{
publicint compare(Object obj1,Object obj2){
Student p1=(Student)obj1;
Student p2=(Student)obj2;
int result=p1.getScore()-p2.getScore();//用学生分数排序;
return result;
}
}
【上机】说明Comparable接口作用。并定义一个学生类,使用分数来比较大小。
自定义类如Student,Product,Person等虽然不是同一类事物,但是都有比较的权利,都可以实现比较的功能。既然是同一功能(比较),就定义一个接口吧,把方法定义在接口里,由各个类去具体实现。
实现Comparable接口的类需要实现compareTo方法,根据该方法可以根据具体的排序规则对容器中的对象进行排序。
publicclass Student implementsComparable{
privateintid;
private String sex;
private String name;
privateint score;
privateintage;
public Student() {
}
public Student(int id, String sex, String name, int score, int age) {
this.id = id;
this.sex = sex;
this.name = name;
this.score = score;
this.age = age;
}
publicint compareTo(Object o) {
Student s = (Student)o;
returnthis.score-s.score;
}
}
Map中,key能否重复?如果重复,会有什么现象?
key:无序,唯一;
添加重复的key不报错,会把之前重复的key覆盖了。
Set和Map的集合类名称相似,有没有内在的联系?
HashMap和HashSet这些集合类采用的是哈希表结构,需要用到hashCode哈希码和equals方法。
【上机】综合使用List、Map容器存放如下数据, 并从map中取出“李四”。
姓名:张三 年龄:18 体重:90 地址:北京
姓名:李四 年龄:28 体重:50 地址:上海
注:不能使用Javabean封装!
先创建Person类;
publicclass Person {
//私有属性;
private String name;
privateint age;
privatedouble weight;
private String address;
//getter和setter方法(略);
//构造方法;
public Person(String name, int age, double weight, String address) {
super();
this.name = name;
this.age = age;
this.weight = weight;
this.address = address;
}
@Override
public String toString() {
return"Person [name=" + name + ", age=" + age + ", weight=" + weight + ", address=" + address + "]";
}
}
用List存放数据:
List
Person p1=new Person("张三",18,90,"北京");
Person p2=new Person("李四",28,60,"上海");
//把Person对象添加到personList里;
personList.add(p1);
personList.add(p2);
用Map存放数据:
Map
//把Person对象添加到map里,用name作为key,Person对象作为value;
map.put(p1.getName(), p1);
map.put(p2.getName(), p2);
//提取名为“李四”的人的信息,用map.get(key)方法,返回的是此key对应的value值;
System.out.println(map.get("李四"));
【上机】使用JavaBean封装,完成上个题目的练习。
【上机】写出List、Set、Map中使用泛型的例子。
ArrayList
Set
Map
使用泛型有什么好处?
泛型是JavaSE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。Java语言引入泛型的好处是安全简单。
【上机】用代码写出遍历List的三种方式
finalintSIZE = list.size();
for (int i = 0; i
System.out.print(s+"");
}
System.out.println();
for (String string : list) {
System.out.print(string+"");
}
System.out.println();
Iterator
while(it.hasNext()){
String s = it.next();
System.out.print(s+"");
}
}
【上机】用代码写出遍历Set的两种方式
1)增强for循环遍历
for (Integer integer : set) {
System.out.print(integer.intValue() + "");
}
2)Iterator 遍历
Iterator
while(iterator.hasNext()){
System.out.print(iterator.next().intValue() + "");
}
【上机】用代码写出遍历map的方式
1:得到所有的key
Set
Iterator
while(iterator.hasNext()){
String key = iterator.next();
System.out.println(key + "--->"+map.get(key));
}
2:得到所有的value
Collection
for (String string : collection) {
System.out.println("value--->"+string);
}
3:得到所有的key和value
Set
Iterator
while (iterator2.hasNext()) {
Entry
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "--->"+value);
}
采用增强for循环遍历List或者Set,如果List或者Set没有加泛型,能遍历吗?
能。
如果我想在遍历时删除元素,采用哪种遍历方式最好?
Iterator接口。Iterator有remove方法可以移除元素。
Iterator是一个接口还是类?
Iterator接口。
Collection和Collections有什么区别?
Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。
Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
资源文件有什么作用?
资源文件是用来配置信息的,如数据库信息,键值对信息等。程序里需要有个方法来读取资源文件中的配置信息。如果没有资源文件,配置信息就得写在代码里;需要修改信息时就不得不修改代码。有了资源文件之后,一旦信息需要改变,修改资源文件就可以,不用修改代码,更好的保证了代码的封装性。
【上机】在src下建立一个资源文件(不包含中文),尝试使用Property类读取里 面的属性。
创建资源文件,我的是fruit.properties; “fruit”可以自定义,后缀名是“properties”。我写的文件内容如下(水果名对应的水果信息:名称,产地,价钱):
apple=name:apple,place:ShanDong,price:7.00RMB/500g
orange=name:orange,place:GuangDong,price:3.99RMB/500g
banana=name:banana,place:HaiNan,price:2.99RMB/500g
carrot=name:carrot,place:Beijing,price:2.98RMB/500g
代码部分:
publicclass TestProperties {
publicstaticvoid main(String[] args) throws IOException {
File file=new File("fruit.properties");//参数是文件路径;
InputStream is=new FileInputStream(file);//建立此文件的输入流;
Properties p=new Properties();//创建资源文件对象;
p.load(is);//加载资源文件
String fruitInfo=p.getProperty("orange");//getProperty()的参数是资源文件中的key值,可以输入“apple”,“orange”,“banana”,”carrot”.
System.out.println(fruitInfo);//fruitInfo是通过输入的key值获得的水果信息。
}
}
【上机】使用entrySet方法遍历Map。
Set
Iterator
while (iterator2.hasNext()) {
Entry
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "--->"+value);
}
Vector和ArrayList的区别联系
Vector和ArrayList的区别和联系
实现原理相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
两者的主要区别如下
Vector是早期JDK接口,ArrayList是替代Vector的新接口
Vector线程安全,ArrayList重速度轻安全,线程非安全
长度需增长时,Vector默认增长一倍,ArrayList增长50%
Hashtable和HashMap的区别联系
实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用
两者的主要区别如下
Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口
Hashtable继承Dictionary类,HashMap实现Map接口
Hashtable线程安全,HashMap线程非安全
Hashtable不允许null值,HashMap允许null值
Java主要容器的选择依据和应用场合
(1) HashTable,Vector类是同步的,而HashMap,ArrayList不是同步的。 因此当在多线程的情况下,应使用 HashTable和 Vector,相反则应使用HashMap,ArrayList.
(2) 除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们 的效率更高。
(3) ArrayList 由数组构建, LinkList由双向链表构建,因此在程序要经常添加,删除元素时速度要快些,最好使用LinkList,而其他情况下最好使用ArrayList.因 为他提供了更快的随机访问元素的方法。
阶段项目课程4
【项目】我的京东商城
练习目标:
选择合适的容器类型
使用容器存储商品和购物车条目
基本分层思想训练
购物车和购物车条目的设计
要求:
完成商品的添加和查询功能
完成购物车条目的添加和删除操作
根据老师课程讲解,完成项目
扩展:
按照自己的思路和老师的代码模板,设计一个小的作业项目。
将上一个作业作业录制成自己的教学视频。
第九章 IO流技术
IO是什么意思? data source是什么意思?
IO:Input Output;
data source:数据源。
字节流和字符流有什么区别?输入流和输出流有什么区别?
字符流和字节流是流的一种划分,按照处理流的数据单位进行的划分。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使用的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。这四个都是抽象类。字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。字节流是最基本的,所有的InputStrem和OutputStream的子类都是字节流,主要用在处理二进制数据,它是按字节来处理的。但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的编码来处理,也就是要进行字符集的转化,这两个之间通过 InputStreamReader,OutputStreamWriter(转换流)来关联,实际上是通过byte[]和String来关联的。
流就像管道一样,在程序和文件之间,输入输出的方向是针对程序而言,向程序中读入东西,就是输入流,从程序中向外读东西,就是输出流。输入流是得到数据,输出流是输出数据。
节点流和处理流有什么区别?
节点流和处理流是流的另一种划分,按照功能不同进行的划分。节点流,可以从或向一个特定的地方(节点)读写数据。处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
word文档能使用字符流操作吗?为什么?
不能。因为word文档不是纯文本文件,除了文字还包含很多格式信息。不能用字符流操作。可以用字节流操作。
【上机】完成老师课堂上读入文件数据的代码:
解释下面代码的含义:
通过上例得知fis是字节输入流对象,fis.read()是每次从指定文件读取一个字节,返回值是这个字节所代表的int类型的整数。如果读到文件结尾(没有内容可读了),那么返回-1。
下面的代码是依次读取文件,每次一个字节,循环读取;每次读完后将返回的整数值(m)转成char类型的数据(强转)(从而知道每次读取的是什么字符),输出这个字符。直到读完为止。
流对象使用完后,一般要调用close方法关闭,释放资源。 这种做法对吗?
对。
【上机】完成老师写文件的操作:
InputStream和OutputStream基本特点是?
二者都是【字节】输入输出流的抽象父类。以字节为单位处理数据,每次读取/写入一个字节。适合处理二进制文件,如音频、视频、图片等。实现类有FileInputStream和FileOutputStream等。
Reader和Writer的基本特点是?
二者都是【字符】输入输出流的抽象父类。以字符为单位处理数据,每次读取/写入一个字符。适合处理文本文件。实现类有FileReader和FileWriter等。
FileInputStream和FileOutputStream的基本作用是?
二者都是【字节】输入输出流的实现类,其抽象父类是InputStream和OutputStream。以字节为单位处理数据,每次向/从指定文件读取/写入一个字节。适合处理二进制文件,如音频、视频、图片等。
FileReader和FileWriter的作用是?
二者都是【字符】输入输出流的实现类,其抽象父类是Reader和Writer。以字符为单位处理数据,每次向/从指定文件读取/写入一个字符。适合处理文本文件。
【上机】完成文件的copy代码
思路:先把源文件读到程序里,在从程序写到目标文件。
代码示例:
//1.创建数据源文件;
File file=new File("e:\picture1.jpg");
//2.搭建输入流管道;
InputStream is=new FileInputStream(file);
//3.创建目的地文件;
File file1=new File("e:\picture2.jpg");
//4.搭建输出流管道;
OutputStream os=new FileOutputStream(file1);
int b=0;
//每次从源文件读出一个字节(b=is.read()),就向目标文件写入一个字节
//(os.write(b));
while((b=is.read())!=-1){
os.write(b);
}
//读写全部完成后关闭资源;
os.close();
is.close();
}
BufferInputStream和BufferedOutputStream的特点是?
BufferInputStream和BufferedOutputStream分别是【缓冲】字节输入输出流,还有【缓冲】字符输入输出流(BufferReader和BufferedWriter)。
缓冲流是处理流,它不直接连接数据源/目的地,而是以一个节点流为参数,在节点流的基础上,提供一些简单操作。
先说不带缓冲的流的工作原理吧:它读取到一个字节/字符,就向用户指定的路径写出去,读一个写一个,所以就慢了。带缓冲的流的工作原理:读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次性写出去,从而提高了工作效率
优点:减少对硬盘的读取次数,降低对硬盘的损耗。
【上机】使用BufferedReader和BufferedWriter实现文本文件的拷贝。
//第一部分:准备从文件读数据到程序;
Reader reader=new FileReader(new File("e:\a.txt"));//创建读取对象reader;
BufferedReader br=new BufferedReader(reader); //创建缓冲流包装reader;
//第二部分:准备从程序写到文件;
Writer writer=new FileWriter(new File("e:\a3.txt"));//创建写入对象writer;
BufferedWriter bw=new BufferedWriter(writer);//创建缓冲流包装writer;
String str=null;
//用循环边读(str=br.readLine())边写(bw.write(str));
while((str=br.readLine())!=null){
bw.write(str);
bw.newLine();
}
bw.flush();//清空缓冲区;
//copy完成后关闭资源;
bw.close();
br.close();
}
InputStreamReader和OutputStreamWriter的作用是?
二者都是转换流,从字节流转换为字符流,是包装流,以一个节点流为参数;提供一些方便读写【字符】的方法。
代码示例(InputStreamReader):
publicstaticvoid main(String[] args) throws IOException {
//1.节点流;
InputStream is=new FileInputStream(new File("e:\a1.txt"));
//2.处理流:把字节流转换成了字符流;
InputStreamReader isr=new InputStreamReader(is,"utf-8");
int temp=0;
//用转换流对象isr进行读取操作,以字符(而不是字节)为单位读取文本文件,方便操//作。
while((temp=isr.read())!=-1){
System.out.print((char)temp);
}
isr.close();
}
OutputStreamWriter(略).
PrintStream打印流经常用于什么情况? System.out 是不是打印流?
PrintStream:字节打印流,是OutputStream的实现类。提供了多个重载的print,println等方法,可以方便地向文本文件中写入数据。
System.out是字节打印流(PrintStream的对象),它被称作标准的输出流,输出的目的地是标准的输出设备,即显示器。所以,当我们使用System.out.print或System.out.println时会向屏幕(显示器)输出数据。
PrintStream的继承关系:
【上机】实现字节数组和任何基本类型和引用类型执行的相互转换。
提示:使用ByteArrayInutStream和ByteArrayOutputStream。
字节数组和基本数据类型之间的转换,以boolean类型为例:
输出一个boolean类型的数据:
boolean flag=true;//先定义一个boolean类型的变量;
ByteArrayOutputStream baos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOututStream(baos);
dos.writeBoolean(flag);
byte[] b=baos.toByteArray();
//接下来可以把byte数组构建成一个数据包(DatagramPacket)发送出去;
读取一个boolean类型的数据:
byte[] b=new byte[1024];
//我们已接收到包含一个boolean类型数据的数据包(代码略);数据信息已经包含在byte数组b里,接下来就把boolean类型的数据读出来并保持原类型;
ByteArrayInputStream bais=new ByteArrayInputStream(b);
DataInputStream dis=new DataInputStream(bais);
boolean flag=dis.readBoolean();//这样数据就读出来了并保持着原来的数据类型。
字节数组和引用类型之间的转换:
输出一个引用类型信息:
//先建一个类,如User(代码略);
User user=new User();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(user);
byte[] b=baos.toByteArray();
//接下来可以把byte数组构建成一个数据包(DatagramPacket)发送出去;
读取一个引用类型信息:
byte[] b=new byte[1024];
//我们已接收到包含一个User类型数据的数据包(代码略);
//数据信息已经包含在byte数组b里,接下来就把User类型的数据读出来并保持原类型;
ByteArrayInputStream bais=new ByteArrayInputStream(b);
ObjectInputStream ois=new ObjectInputStream(bais);
User user=(User)ois.readObject();//这样数据就读出来了并保持着原来的数据类型。
DataInputStream和DataOutputStream的特点是?
二者都是处理流,要以一个节点流为参数;二者被称为数据流,是用来操作基本数据类型的。用DataInputStream写入一个类型的数据,用DataOutputStream读出数据时可以保持类型不变。如用DataInputStream写入一个int类型的数据,用DataOutputStream读出来的还是一个int数据,即可以直接当作int类型的数据来进行操作,不用做任何转换。
代码示例:
publicclass TestDataInputStream {
publicstaticvoid main(String[] args) throws IOException {
//1.写数据;
OutputStream os=new FileOutputStream(new File("e:\f.data"));//构建节点流;
DataOutputStream dos=new DataOutputStream(os);//用数据流包装节点流;
int n=123456;
String str="尚学堂教育";
dos.writeInt(n);//用数据流写入一个int类型的数值(n是int类型的);
dos.writeUTF(str); //用数据流写入一个String类型的数据;
dos.writeDouble(3.15); //用数据流写入一个double类型的数据;
dos.writeChar('我'); //用数据流写入一个char类型的数据;
dos.writeBoolean(true); //用数据流写入一个布尔类型的数据;
//2.读数据;
InputStream is=new FileInputStream(new File("e:\f.data"));
DataInputStream dis=new DataInputStream(is);
int n1=dis.readInt();//用数据流读出刚才写入的int类型数据,赋给int类型变量;
String str1=dis.readUTF();//用数据流读出String类型的数据;
double d=dis.readDouble();//用数据流读出double类型的数据;
char c=dis.readChar();//用数据流读出char类型的数据;
boolean flag=dis.readBoolean();//用数据流读出布尔类型的数据;
//打印输出用数据流读出来的数据;
System.out.println(n1);
System.out.println(str1);
System.out.println(d);
System.out.println(c);
System.out.println(flag);
//关闭资源;
dis.close();
dos.close();
}
}
结果:
123456
尚学堂教育
3.15
我
true
数据流特点:
写入是什么类型的数据,读出是相应类型的数据;
要先写后读;用DataOutputStream流写,用DataInputStream流读;
读写顺序要一致,否则会报EOF异常;EOF:end of file;
数据流可以跨平台写入和读出,适合网路应用。
【上机】使用ObjectInputstream和ObjectOutputStream实现将某个对象存 储到硬盘上,然后再读到程序中。
见课堂实例。
中文乱码是怎么造成的?
字符流的读写根据需要设置编码方式,编码方式设置不当会出现中文乱码。
unicode字符集是几个字节表示一个字符?为什么需要utf-8?
Unicode字符集中2个字节表示一个字符。
序列化和反序列化指的是什么?
(1) 序列化:
将对象以byte流的形式写入到文件中->序列化;
将要被序列化的对象的类要实现Serializable接口:
publicclassUserimplements Serializable {
//略;
}
User实现了这个接口,代表User这个类的对象具有了将对象以byte流的形式写进文件的功能。
(2) 反序列化:
将文件中的数据以byte流的形式读到程序中来,依然是一个对象反序列化。
想序列化某个类的对象,该类必须实现sierializable接口吗?
要序化的对象必须实现Serializable接口,以启动序列化的功能。
说说sierializable接口的特点。
- 需要被序列化的对象的类必须实现Serializable接口。
- 给类加个序列化编号,即给类定义一个标记,如:
public static final long serialVersionUID=1L;
新的修改后的类还可以操作曾经序列化的对象。
3、静态是不能被序列化的,
序列化只能对堆中的对象进行序列化 ,不能对”方法区”中的对象进行序列化。
4、不需要序列化的字段前加 transient,如:
private transient String password;
transient的作用是?
不希望序列化的属性,可以添加transient关键字;
密码字段是非常敏感的字段,所在在序列化时,不允许写到文件:
private transient String password;
【上机】完成目录的copy代码(结合递归算法)
import java.io.;
/*
CopyDocJob定义了实际执行的任务,即
-
从源目录拷贝文件到目标目录
/
public class CopyDir2 {
public static void main(String[] args) {
try {
copyDirectiory("d:/301sxt","d:/301sxt2");
} catch (IOException e) {
e.printStackTrace();
}
}
/*- 复制单个文件
- @param sourceFile 源文件
- @param targetFile 目标文件
- @throws IOException
*/
private static void copyFile(File sourceFile, File targetFile) throws IOException {
BufferedInputStream inBuff = null;
BufferedOutputStream outBuff = null;
try {
// 新建文件输入流
inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
// 新建文件输出流
outBuff=new BufferedOutputStream(new FileOutputStream(targetFile));
// 缓冲数组
byte[] b = new byte[1024 * 5];
int len;
while ((len = inBuff.read(b)) != -1) {
outBuff.write(b, 0, len);
}
// 刷新此缓冲的输出流
outBuff.flush();
} finally {
// 关闭流
if (inBuff != null)
inBuff.close();
if (outBuff != null)
outBuff.close();
}
}
/**
- 复制目录
- @param sourceDir 源目录
- @param targetDir 目标目录
- @throws IOException
*/
private static void copyDirectiory(String sourceDir, String targetDir) throws IOException {
// 检查源目录
File fSourceDir = new File(sourceDir);
if(!fSourceDir.exists() || !fSourceDir.isDirectory()){
return;
}
//检查目标目录,如不存在则创建
File fTargetDir = new File(targetDir);
if(!fTargetDir.exists()){
fTargetDir.mkdirs();
}
// 遍历源目录下的文件或目录
File[] file = fSourceDir.listFiles();
for (int i = 0; i < file.length; i++) {
if (file[i].isFile()) {
// 源文件
File sourceFile = file[i];
// 目标文件
File targetFile = new File(fTargetDir, file[i].getName());
copyFile(sourceFile, targetFile);
}
//递归复制子目录
if (file[i].isDirectory()) {
// 准备复制的源文件夹
String subSourceDir = sourceDir + File.separator + file[i].getName();
// 准备复制的目标文件夹
String subTargetDir = targetDir + File.separator + file[i].getName();
// 复制子目录
copyDirectiory(subSourceDir, subTargetDir);
}
}
}
}
【上机】假设从入学开始所有书写的Java代码都在d:/sxtjava文件夹下,包括多
级子文件夹。使用IO流获取从入学开始,到目前为止已经写了多少行Java代码。
提示:获取d:/sxtjava文件夹及其子文件夹下的所有.java文件,使用readLine()读取其中每一行,每读取一行,行数加1。
public class TestCountDir {
private int count;
/**
* 统计一个java文件的行数
/
private void countLine(File sourceFile) throws IOException {
BufferedReader br = null;
try {
// 新建文件输入流
br = new BufferedReader(new FileReader(sourceFile));
while(br.readLine()!=null){
count++;
//System.out.println(count);
}
} finally {
br.close();
}
}
/*
* 统计一个目录下所有Java文件的行数
*/
private void countDir(String sourceDir) throws IOException {
// 检查源目录
File fSourceDir = new File(sourceDir);
if(!fSourceDir.exists() || !fSourceDir.isDirectory()){
System.out.println("源目录不存在");
return;
}
// 遍历目录下的文件或目录
File[] file = fSourceDir.listFiles();
for (int i = 0; i < file.length; i++) {
if (file[i].isFile()) {
if(file[i].getName().toLowerCase().endsWith(".java")){
// System.out.println(file[i].getName());
countLine(file[i]);
}
}
//递归统计代码行数
if (file[i].isDirectory()) {
// 准备统计的文件夹
String subSourceDir = sourceDir + File.separator + file[i].getName();
// 统计子目录
countDir(subSourceDir);
}
}
}
public static void main(String[] args) throws IOException {
TestCountDir tcd = new TestCountDir();
tcd.countDir("d:/sxtjava");
System.out.println(tcd.count);
}
}
【上机】下载并自学apache commons中的IO工具包。
第十章 多线程
程序、进程、线程的区别是什么? 举个现实的例子说明。(网上查资料,跟老师的不一样)
程序(Program):是一个指令的集合。程序不能独立执行,只有被加载到内存中,系统为它分配资源后才能执行。
进程(Process):如上所述,一个执行中的程序称为进程。
进程是系统分配资源的独立单位,每个进程占有特定的地址空间。
程序是进程的静态文本描述,进程是程序在系统内顺序执行的动态活动。
线程(Thread):是进程的“单一的连续控制流程“。
线程是CPU调度和分配的基本单位,是比进程更小的能独立运行的基本单位,也被称为轻量级的进程。
线程不能独立存在,必须依附于某个进程。一个进程可以包括多个并行的线程,一个线程肯定属于一个进程。Java虚拟机允许应用程序并发地执行多个线程。
举例:如一个车间是一个程序,一个正在进行生产任务的车间是一个进程,车间内每个从事不同工作的工人是一个线程。
【上机】Java中通过哪些方式创建多线程类? 分别使用代码说明。并调用之。
自定义线程类继承Thread:
public class MyDefinedThread extends Thread{
//重写run()方法;
public void run(){
//把线程需要执行的任务写在run()方法里;
}
public static void main(String[] args){
MyDefinedThread mdt=new MyDefinedThread();
mdt.start(); //启动线程。
}
}
(2) 自定义类实现Runnable接口;
public class MyRunnable implements Runnable{
//实现run()方法;
public void run(){
//把线程需要执行的任务写在run()方法里;
}
public static void main(String[] args){
MyRunnable mr=new MyRunnable();
Thread th=new Thread(mr);//”mr”并不是一个线程对象,而是要作为参数传递到Thread的构造方法中;“th“才是一个线程对象。
th.start;//启动线程。
}
}
Thread类有没有实现Runnable接口?
有实现。
当调用一个线程对象的start方法后,线程马上进入运行状态吗?
不是,只是进入就绪(可运行)状态,等待分配CPU时间片。一旦得到CPU时间片,即进入运行状态。
下面的代码,实际上有几个线程在运行:
两个:线程t和main()方法(主线程)。
说说:sleep、yield、join方法的区别。
sleep():在指定时间内让线程暂停执行,进入阻塞状态。
在指定时间到达后进入就绪状态。线程调用sleep()方法时,释放CPU当不释放对象锁(如果持有某个对象的锁的话)。
join(): 当前线程等待调用此方法的线程执行结束再继续执行。如:在main方法中调用t.join(),那main方法在此时进入阻塞状态,一直等t线程执行完,main方法再恢复到就绪状态,准备继续执行。
yield(): 调用该方法的线程暂停一下,回到就绪状态。所以调用该方法的线程很可能进入就绪状态后马上又被执行。
为什么不推荐使用stop和destroy方法来结束线程的运行?
stop():此方法可以强行中止一个正在运行或挂起的线程。但stop方法不安全,就像强行切断计算机电源,而不是按正常程序关机。可能会产生不可预料的结果。举例来说:
当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常。这里的“立即”因为太“立即”了,假如一个线程正在执行:
synchronized void {
x = 3;
y = 4;
}
由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记 线程的stop方法,以后我们再也不要说“停止线程”了。
destroy():该方法最初用于破坏该线程,但不作任何资源释放。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以 suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。
【上机】写个代码说明,终止线程的典型方式。
当run()方法执行完后,线程就自动终止了。
但有些时候run()方法不会结束(如服务器端监听程序),或者其它需要用循环来处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面通过例子来说明:
public class ThreadFlag extends Thread { public volatile boolean exit = false; public void run() { while (!exit); } public static void main(String[] args) throws Exception { ThreadFlag thread = new ThreadFlag(); thread.start(); sleep(5000); // 主线程延迟5秒 thread.exit = true; // 终止线程thread thread.join(); System.out.println("线程退出!"); } }
在上面代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值。
A线程的优先级是10,B线程的优先级是1,那么当进行调度时一定会调用A吗?
不一定。线程优先级对于不同的线程调度器可能有不同的含义,可能并不是用户直观的推测。
【上机】模仿老师课堂例子,完成账户取钱的模拟操作代码。
synchronize修饰在方法前是什么意思?
一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
synchronize修饰的语句块,如下面的代码。是表示该代码块运行时必须获得 account对象的锁。如果没有获得,会有什么情况发生?
如果没有获得account对象的锁,就不能执行synchronize修饰的语句块,包括此语句块,还有其他需要获得此account对象锁才能执行的同步代码块和同步方法。
【上机】死锁是怎么造成的?用文字表达。再写一个代码示例。
过多的线程同步会引起死锁。如两个线程都在等待对方释放锁才能继续执行,有时会出现僵持局面:两个线程都持有对方需要的锁,而两个线程都需要对方释放锁了才能继续运行。举例来说:
我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由桥的两端驶上该桥,则对于A车来说,它走过桥面左面的一段路(即占有了桥的一部分资源),要想过桥还须等待B车让出右边的桥面,此时A车不能前进;对于B车来说,它走过桥面右边的一段路(即占有了桥的一部分资源),要想过桥还须等待A车让出左边的桥面,此时B车也不能前进。两边的车都不倒车,结果造成互相等待对方让出桥面,但是谁也不让路,就会无休止地等下去。这种现象就是死锁。死锁是程序运行时出现的一种问题,是需要避免的。
代码示例:
publicclass DeadLock{
Object A=new Object();
Object B=new Object();
publicvoid toEast(){
synchronized(A){
synchronized(B){
System.out.println("向东行驶。");
}
}
}
publicvoid toWest(){
synchronized(B){
synchronized(A){
System.out.println("向西行驶。");
}
}
}
}
publicclass ToEastThread extends Thread {
DeadLock d=new DeadLock();
public ToEastThread(DeadLock d) {
super();
this.d = d;
}
publicvoid run(){
d.toEast();
}
}
publicclass ToWestThread extends Thread {
DeadLock d=new DeadLock();
public ToWestThread(DeadLock d) {
super();
this.d = d;
}
publicvoid run(){
d.toWest();
}
}
publicclass Test1 {
publicstaticvoid main(String[] args) {
DeadLock d=new DeadLock();
ToEastThread et=new ToEastThread(d);
ToWestThread wt=new ToWestThread(d);
et.start();
wt.start();
}
}
使用Timer和TimerTask实现定时执行,定时在每天下午17:00执行。
知识点简介:
Timer:定时器,实际上是个线程,定时调度所拥有的TimerTasks。
TimerTask:一个拥有run方法的类,需要定时执行的代码放到run方法体内。 TimerTask一般是以匿名类的方式创建。
语法简介:
java.util.Timer timer = new java.util.Timer(true);
// true 说明这个timer以daemon方式运行(优先级低,
// 程序结束timer也自动结束),注意,javax.swing
// 包中也有一个Timer类,如果import中用到swing包,
// 要注意名字的冲突。
TimerTask task = new TimerTask() {
public void run() {
... //每次需要执行的代码放到这里面。
}
};
用法简介:
//以下是几种调度task的方法:
timer.schedule(task, time);
// time为Date类型:在指定时间执行一次。
timer.schedule(task, firstTime, period);
// firstTime为Date类型,period为long
// 从firstTime时刻开始,每隔period毫秒执行一次。
timer.schedule(task, delay)
// delay 为long类型:从现在起过delay毫秒执行一次
timer.schedule(task, delay, period)
// delay为long,period为long:从现在起过delay毫秒以后,每隔period
// 毫秒执行一次。
举例:
import java.util.TimerTask;
publicclass TimePrintTask extends TimerTask {
int i=1;
publicvoid run(){
System.out.println(i);
i++;
}
}
publicclass Test {
publicstaticvoid main(String[] args) {
Timer timer=new Timer();
//timer.schedule(new TimePrintTask(), 1000, 500);
DateFormat df=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss SS");
Date firstDate=null;
try {
firstDate=df.parse("2016/12/09 17:00:00 00");
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
timer.schedule(new TimePrintTask(),firstDate , 1000);
}
}
wait方法被调用时,所在线程是否会释放所持有的锁资源? sleep方法呢?
wait:释放CPU,释放锁;
sleep:释放CPU,不释放锁。
wait、notify、notifyAll是在Object类中定义的方法吗?作用分别是什么?wait(),notify(),notifyAll()不属于Thread类,而是属于Object类,也就是说每个对象都有wait(),notify(),notifyAll()的功能。因为每个对像都有锁,锁是每个对像的基础,而wait(),notify(),notifyAll()都是跟锁有关的方法。
三个方法的作用分别是:
wait:导致当前线程等待,进入阻塞状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前线程必须拥有此对象监视器(对象锁)。该线程释放对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.
notify:唤醒在此对象监视器(对象锁)上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由作为此对象监视器的所有者的线程来调用.
"当前线程必须拥有此对象监视器"与"此方法只应由作为此对象监视器的所有者的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj之内).
notifyAll: 唤醒在此对象监视器(对象锁)上等待的所有线程。
notify是唤醒所在对象wait pool中的第一个线程吗?
不是。调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择。
【上机】使用线程通信实现生产者-消费者问题。
详见课堂实例。
第十一章 网络编程
什么是计算机网络?网络的主要类型有哪些;
计算机网络是将不同地理位置的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络的主要类型:
按计算机网络的地理覆盖范围分:
局域网(Local Area Network,LAN):
地理范围一般在10km以内,属于一个组织,一个单位或一个部门所有。如:一个企业,一所学校,一座大楼,一间实验室等。
这种网络一般不对外提供公共服务,管理方便,安全保密性好。
组建方便,投资少,见效快,使用灵活,是计算机网络中发展最快,应用最普遍的计算机网络。
与广域网相比,传输速率快,通常100Mbps以上;误码率低。
城域网(Metropolitan Area Network,MAN):
介于局域网和广域网之间,地理范围覆盖几十km到几百km不等,可能是一个地区或一个城市。
广域网(Wide Area Network,WAN):
地理范围一般从几十km到几万km不等,小到一个地区,一个城市,大到一个国家,几个国家乃至全世界。
提供大范围的公共服务。因特网就是典型的广域网。
与局域网相比,广域网投资大,安全保密性差,传输速率慢,通常为64kbps,2Mbps,10Mbps;误码率高。
按计算机网络的拓扑结构分:拓扑结构是数学上的一个名词,从英文Topology音译过来的。在这里,指的是网络传输介质和节点的连接形式,即线路构成的几何形状。
总线型:
该结构采用一条公共总线作为传输介质,每台计算机通过相应的硬件接口入网。信号沿总线进行广播式传送。
是典型的共享传输介质的网络。从信源所发的信息会传送到介质长度所及之处,被其他所有站点看到。如果有两个以上的节点同时发送数据,可能会造成冲突,就像公路上的两车相撞一样。
优点:布线容易;增删容易;节约电缆;
缺点:
任何两个站点传送信息都要经过总线,总线称为传输瓶颈;当计算机站点多时,容易造成信息阻塞,传递不畅。
一台计算机接入总线的接口发生故障,会造成整个网络瘫痪。
当网络发生故障时,故障诊断和隔离困难。
星型:由一台中央节点和周围的从节点组成。中央节点和从节点可以直接通信,而从节点必须经过中央节点转接才能通信。
优点:
I 可靠性高。每台计算机及其接口的故障不会影响其他计算机,不会影响整个网络,也不会造成网络瘫痪。
II 故障诊断和隔离容易,网络容易管理和维护。
III 可扩性好,配置灵活。增删改一个站点容易实现,和其他计算机没有关系。
IV 传输速率高。每个节点独占一条线路,消除了信息阻塞的情况。而总线和环形网络的瓶颈都在线路上。
缺点:
I 线缆使用量大。
II 布线、安装工作量大。
III 网络可靠性依赖于中央节点。如交换机或集线器选择不当,发生故障会造成全网瘫痪。
环型:
计算机通过硬件接口入网,这些接口收尾相连成一条链路。信息传送也是广播式的,沿着一个方向(如逆时针方向)单向逐点传送。
优点:
I 点到点且沿一个方向单向传输,非常适合用光纤作为传输介质。
II 传输距离远,适合做主干网。
III 故障诊断容易定位。
IV 初始安装容易,线缆用量少。环形线路也是一条总线,只是首尾封闭。
按传输介质分:
有线网络:
同轴电缆:成本低,安装方便,但传输率低,抗干扰能力一般,传输距离短;
双绞线:组建局域网时常用,优缺点类似于同轴电缆。
光纤:主要用于网络的主干部分,其特点是成本高,安装技术要求高,传输距离长,传输率高,抗干扰能力强,且不会受到电子监听设备的监听等,是组建高安全性网络的理想选择。
无线网络:
红外线;
微波;
无线电;
常见的网络分层模型有哪两个?哪个更流行?为什么?
OSI/ISO 参考模型:
OSI:(Open System Interconnection),开放式网络互连;
ISO:(International Standard Organization),国际标准化组织;
此模型是由国际标准化组织提出的一种网络互连模型。
OSI参考模型把网络模型分成7层,每一层为上一层提供服务,并为其上一层提供一个访问接口或界面。
TCP/IP协议栈:4层网络模型。OSI参考模型设计得过于庞大、复杂,不易被付诸应用。相比之下,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。
TCP的全称是?
Transfer Control Protocol。
UDP的全称是?
User Datagram Protocol。
请说出TCP和UDP的区别?
TCP:一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transport layer)通信协议 。
特点:
面向连接;
点到点的通信;
高可靠性;
占用系统资源多、效率低;
UDP:一种无连接的、提供面向事务的简单不可靠信息传送服务的传输层通信协议。
特点:
非面向连接
传输不可靠,可能丢失
发送不管对方是否准备好,接收方收到也不确认
可以广播发送
非常简单的协议,开销小
通过类比打电话,详细描述TCP三次握手机制。
第一次握手:客户端发送连接请求给服务器端,等候服务器端确认;
第二次握手:服务器端收到客户端发来的请求,向客户端发送确认连接信息;
第三次握手:客户端接到服务器端发送来的确认连接信息,也要向服务器端再发送一次确认连接信息。至此三次握手完成。客户端和服务器端进入准备传送数据状态。
以打电话为例:
A拨电话给B:
B 接起电话:喂?能听到我吗?
A 回答:可以听到。
然后A和B开始正式通话。
IP的全称是? IP的作用是?
IP:Internet Protocol address,互联网协议地址。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址。
IP的作用:用来标志网络中的一个通信实体的地址。通信实体可以是计算机,路由器等。
IPV4为什么会发生资源枯竭的问题?
IPV4规定IP地址长度为32位, 即有2^32-1个地址(大约40亿多一点);而随着互联网的迅速发展,这个数量很可能满足不了未来的需求。
解决:IPv6。IP地址的长度为128,即有2^128-1个地址。
为什么需要端口?端口是真实存在的还是虚拟的概念?
IP地址用来标志一台计算机,但是一台计算机上可能提供多种网络应用程序,使用端口来区分这些应用程序。
端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。
端口范围0---65535,16位整数。
Java中,端口使用两个字节表示,可以表示多少个端口? UDP和TCP端口是各自独立的吗?
端口范围0---65535,16位整数。
由于TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立,如TCP有一个255号端口,UDP也可以有一个255号端口,二者并不冲突。
InetAddress和InetSocketAddress都封装了哪些信息? 他们两的区别是?
InetAddress:封装计算机的IP地址 ,没有端口。
InetSocketAddress:包含IP地址和端口信息,用于Socket通信的。
URL类有什么作用?
URL:Uniform Resource Locator,统一资源定位器;俗称“网址”,如:
"http://www.baidu.com:80/index.html#aa?cansu=bjsxt“
由4部分组成:
协议: http;
存放资源的主机域名:www.baidu.com;
端口号:80;
资源文件名: index.html#aa?cansu=bjsxt;
URL是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
【上机】将网络上一张图片或一个mp3或一个视频的信息保存到本地。
查资料了解,SNS是什么?
如何理解Socket的含义?
所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则是使用套接字来进行分离。
套接字就像是传输层为应用层开的一个小口,应用程序通过这个小口向远程发送数据,或者接收远程发来的数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,是不知道也不需要知道的,也不会关心它如何传输,这属于网络其它层次的工作。
Socket实际是传输层供给应用层的编程接口。传输层则在网络层的基础上提供进程到进程问的逻辑通道,而应用层的进程则利用传输层向另一台主机的某一进程通信。Socket就是应用层与传输层之间的桥梁。
使用Socket编程可以开发客户机和服务器应用程序,可以在本地网络上进行通信,也可通过Internet在全球范围内通信。
生活案例1如果你想写封邮件发给远方的朋友,如何写信、将信打包,属于应用层。信怎么写,怎么打包完全由我们做主;而当我们将信投入邮筒时,邮筒的那个口就是套接字,在进入套接字之后,就是传输层、网络层等(邮局、公路交管或者航线等)其它层次的工作了。我们从来不会去关心信是如何从西安发往北京的,我们只知道写好了投入邮筒就OK了。
生活案例2:可以把Socket比作是一个港口码头,应用程序只要将数据交给Socket,就算完成了数据的发送,具体细节由Socket来完成,细节不必了解。同理,对于接收方,应用程序也要创建一个码头,等待数据的到达,并获取数据。
基于TCP的Socket网络编程的主要步骤是什么?
Java分别为TCP和UDP 两种通信协议提供了相应的Socket编程类,这些类存放在java.net包中。与TCP对应的是服务器的ServerSocket和客户端的Socket,与UDP对应的是DatagramSocket。
基于TCP创建的套接字可以叫做流套接字,服务器端相当于一个监听器,用来监听端口。 服务器与客服端之间的通讯都是输入输出流来实现的。基于UDP的套接字就是数据报套接字,• 两个都要先构造好相应的数据包。
基于TCP协议的Socket编程的主要步骤
服务器端(server):
- 构建一个ServerSocket实例,指定本地的端口。这个socket就是用来监听指定端口的连接请求的。
2.重复如下几个步骤:
a. 调用socket的accept()方法来获得下面客户端的连接请求。通过accept()方法返回的socket实例,建立了一个和客户端的新连接。
b.通过这个返回的socket实例获取InputStream和OutputStream,可以通过这两个stream来分别读和写数据。
c.结束的时候调用socket实例的close()方法关闭socket连接。
客户端(client):
1.构建Socket实例,通过指定的远程服务器地址和端口来建立连接。
2.通过Socket实例包含的InputStream和OutputStream来进行数据的读写。
3.操作结束后调用socket实例的close方法,关闭。
【上机】写出建立TCP服务器ServerSocket的代码。并说明accept方法有什么特点?
//服务器监听请求;
ServerSocket ss=new ServerSocket(9999);
//接受请求:创建了socket;
Socket socket=ss.accept();
详见课上示例。
【上机】写出建立TCP客户端Socket的代码。并说明建立Socket后,通过什么方法Socket获得流对象?
//客户端向服务器端发送请求;
Socket socket=new Socket("127.0.0.1",9999);
//建好连接后,开始传输数据;
OutputStream os=socket.getOutputStream();
详见课上示例。
【上机】完成老师课堂上的代码(最简单的服务器客户端代码。可双向交流的服务 器客户端代码。本作业可课后完成)
详见课上示例。
基于UDP的Socket网络编程的主要步骤是什么?
基于UDP协议的Socket编程的主要步骤
服务器端(server):
- 构造DatagramSocket实例,指定本地端口。
- 通过DatagramSocket实例的receive方法接收DatagramPacket.DatagramPacket中间就包含了通信的内容。
- 通过DatagramSocket的send和receive方法来收和发DatagramPacket.
客户端(client): - 构造DatagramSocket实例。
2.通过DatagramSocket实例的send和receive方法发送DatagramPacket报文。
3.结束后,调用DatagramSocket的close方法关闭。
【上机】使用UDP的方式,完成对象的传递。
(1)客户端向服务器端传送对象信息;
DatagramSocket ds=new DatagramSocket(9999);
//构建数据包;
Scanner input=new Scanner(System.in);
System.out.println("请输入用户名:");
String username=input.nextLine();
System.out.println("请输入密码:");
String password=input.nextLine();
//事先要创建好User类;
User user=new User(username,password);
//字节流;在内存开辟缓冲区;
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(user);
byte buf[]=baos.toByteArray();
DatagramPacket dp=new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 8888);//DatagramPacket只用byte[]数组;
//发送数据;
ds.send(dp);
(2)服务器端从客户端接收对象信息;
//服务器定义DatagramSocket以接收数据;
DatagramSocket ds=new DatagramSocket(8888);
//定义一个数据包来接收数据;
//数据包里是byte数组,所以还得定义一个byte数组;
byte buf[]=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf, buf.length);
//接收客户端发过来的数据;
ds.receive(dp);
//用字节流和对象流读取对象信息;
ByteArrayInputStream bais=new ByteArrayInputStream(buf);
ObjectInputStream ois=new ObjectInputStream(bais);
User user=(User)ois.readObject();
System.out.println(user);
详见课上示例。
项目阶段课程5
【项目】自定义聊天室/自定义web服务器Tomcat
练习目标:
按照面向对象的思维方式写出相关项目
熟练使用容器、数组、IO、多线程、网络通信相关技术
要求:
结合容器(将Socket对象放到容器中),写出较完整的聊天室程序
扩展作业(自由思考、自由查找资料。不讲解):
每三人组成临时小组,选定课题。(飞鸽传书、视频广播、迅雷、聊天室系统等,或自己向老师提出课题)
录制讲解自己完成的项目
附:内部类专题(自学)
方法内部能不能定义类?
可以,是方法内部类。
请说明定义内部类的方式,并说明适用于什么情况?
成员内部类:定义在另一个类(外部类)的内部,而且与成员方法和属性平级,属于类的一个成员,可以用private,默认,protected,public四个访问修饰符修饰。
外部类无法直接访问成员内部类的方法和属性,需要通过内部类的一个实例来访问。
调用方式:外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)。
静态内部类:被static修饰的成员内部类叫静态内部类。
调用方式:外部类名.内部类名 实例名 = new 外部类名.内部类名(参数)。
局部内部类:定义在代码块或方法体内的类叫局部内部类。
局部内部类只能在代码块和方法体内使用(如创建对象和使用类对象等)。
匿名内部类:特殊的局部内部类。
必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。如果父类(或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法。
只能使用一次,创建实例之后,类定义会立即消失。创建:父类(接口) 实例名 = new 父类(){
//匿名内部类需要实现的功能。
}
匿名内部类不能再是抽象类,因为匿名内部类在定义之后,会立即创建一个实例。
匿名内部类不能定义构造方法,匿名内部类没有类名,无法定义构造方法,但是,匿名内部类拥有与父类相同的所有构造方法。
可以定义代码块,用于实例的初始化。
普通成员内部类能不能直接访问外部类的普通成员?
普通成员内部类可以直接访问外部类的成员,如上例:内部类中的innerMethod()方法:
public void innerMethod(){
int num = 40;
System.out.println(OuterClass.this.num);//外部类的成员变量;
System.out.println(this.num);//30
System.out.println(num);//40
System.out.println(name);
}
【上机】写出:调用普通成员内部类的典型方式。
创建成员内部类的实例使用:外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)。
创建包含内部类的外部类:
public class OuterClass {
//成员变量
private int num=20;
private String name;
//构造方法
public OuterClass() {
super();
}
public OuterClass(String name) {
super();
this.name = name;
}
//成员方法
public void execInnerClass(){
this.name = "abc";
InnerClass ic = new InnerClass();
//ic.num=30;
ic.innerMethod();
}
//内部类
public class InnerClass{
private int num=30;
public InnerClass() {
super();
}
public InnerClass(int num) {
super();
this.num = num;
}
public void innerMethod(){
int num = 40;
System.out.println(OuterClass.this.num);//20
System.out.println(this.num);//30
System.out.println(num);//40
System.out.println(name);
}
}
}
调用成员内部类:两种常用方法;
先创建外部类对象,由外部类对象创建内部类对象
格式:外部类名.内部类名对象名 = 外部类对象.内部类对象;
OuterClass oc2 = new OuterClass();
OuterClass.InnerClass ic = oc2.new InnerClass();
创建外部类对象,外部类的方法操作内部类
OuterClass oc = new OuterClass();
oc.execInnerClass();
静态成员内部类能不能直接访问外部类普通成员?能不能访问外部类静态成员?
静态内部类
1.不能访问外部类的非静态成员(变量或者方法)。
2.可以访问外部类的静态成员。
【上机】写出:调用静态内部类的典型方式。
创建包含静态内部类的外部类:
public class OuterClass{
//成员变量
private static int num=20;
private static String name;
//构造方法
public OuterClass() {
super();
}
public OuterClass(String name) {
super();
this.name = name;
}
//成员方法
public void execInnerClass(){
this.name = "abc";
InnerClass ic = new InnerClass();
//ic.num=30;
ic.innerMethod();
}
//内部类
public static class InnerClass{
private int num=30;
public InnerClass() {
super();
}
public InnerClass(int num) {
super();
this.num = num;
}
public void innerMethod(){
int num = 40;
//System.out.println(OuterClass.this.num);//20
System.out.println(OuterClass.num);
System.out.println(this.num);//30
System.out.println(num);//40
System.out.println(name);
}
}
}
(2)静态内部类对象可以直接创建实例,不必依附于外部类实例:
OuterClass.InnerClass ic = new OuterClass.InnerClass();
格式:外部类名.内部类名对象名 = new 外部类名.内部类名();
什么时候会使用匿名内部类?
有些情况下,某些类创建对象一次后再也不使用了。这种情况下就可以不提供有名字的类,而是使用匿名内部类。
线程池专题(自学)
什么是线程池?
多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单 元的闲置时间,增加处理器单元的吞吐能力。假设一个服务器完成一项任务所需时间为:T1---创建线程时间,T2---在线程中执行任务的时间,T3---销毁线程时间。如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。一个线程池包括以下四个基本组成部分:1. 线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池, 销毁线程池,添加新任务;2. 工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可 以循环的执行任务;3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行, 它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;4. 任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。 线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性 能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的 时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一 个例子:假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完 成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程 的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般 线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000 而在处理请求时浪费时间,从而提高效率。
线程池的好处有哪些?
减少在创建和销毁线程上所花的时间以及系统资源的开销;
如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。
如何创建一个线程池,常用输入参数的含义?
- Executors.newCachedThreadPool()
Executors.newCachedThreadPool(ThreadFactory threadFactory)
newCachedThreadPool创建一个可缓存的线程池。
这种类型的线程池特点是:
1)工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2)如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3)参数threadFactory - 表示用来创建线程的线程工厂,在需要时使用提供的 ThreadFactory 创建新线程。
2.newFixedThreadPool(int nThreads)
newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
参数nThreads - 表示池中的线程数。
参数threadFactory - 表示用来创建线程的线程工厂,在需要时使用提供的 ThreadFactory 创建新线程。
3.newSingleThreadExecutor()
newSingleThreadExecutor(ThreadFactory threadFactory)
newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
参数threadFactory - 表示用来创建线程的线程工厂,在需要时使用提供的 ThreadFactory 创建新线程。
4.newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
参数corePoolSize - 核心池的大小
参数threadFactory - 表示用来创建线程的线程工厂,在需要时使用提供的 ThreadFactory 创建新线程。
分析线程池的主要工作流程。
如何监控线程池?
【上机】查资料,完成一个简单的自定义的线程池,对线程池底层原理更加熟悉。
【上机】完成课上线程池调用测试代码。
附3:设计模式初步专题(自学,适合初级.更深入的会在框架阶段)
什么是设计模式?
设计模式是一套被反复使用的、多数人知晓、经过分类编目的优秀代码设计经验的总结。特定环境下特定问题的处理方法。
重用设计和代码 重用设计比重用代码更有意义,自动带来代码重用
提高扩展性 大量使用面向接口编程,预留扩展插槽,新的功能或特性很容易加入到系统中来。
提高灵活性 通过组合提高灵活性,可允许代码修改平稳发生,对一处修改不会波及到其他模块。
提高开发效率 正确使用设计模式,可以节省大量的时间。
设计模式的优点有哪些?
23种经典设计模式都有哪些,如何分类?
面向对象的设计原则有哪些?
面向对象设计原则是面向对象设计的基石,面向对象设计质量的依据和保障,设计模式是面向对象设计原则的经典应用。
单一职责原则 :SRP
开闭原则:OCP
里氏替代原则:LSP
依赖注入原则:DIP
接口分离原则:ISP
迪米特原则:LOD
组合/聚合复用原则:CARP
开闭原则具有理想主义色彩,它是面向对象设计的终极目标。其它设计原则都可以看作是开闭原则的实现手段或方法。
开闭原则的含义和实现。
依赖注入原则的含义和实现。
【上机】使用简单工厂模式实现可以进行四则运算的运算器
【上机】使用工厂方法模式完善可以进行四则运算的运算器
【上机】写出饿汉式、懒汉式的单例模式。
结合Java IO流体系说明装饰模式。
java IO中需要完成对不同输入输出源的操作,如果单纯的使用继承这一方式,无疑需要很多的类。比如说,我们操作文件需要一个类,实现文件的字节读取需要一个类,实现文件的字符读取又需要一个类....依次类推每个特定的操作都需要一个特定的类。这无疑会导致大量的IO继承类的出现。显然对于编程是很不利的。
而使用装饰模式则可以很好的解决这一问题,在装饰模式中:节点流(如FileInputStream)直接与输入源交互,之后通过过滤流(FilterInputStream)进行装饰,这样获得的io对象便具有某几个的功能,很好的拓展了IO的功能。
结合InputStreamReader类说明适配器模式。
请选择一个对你所熟悉的一个设计模式进行介绍。
XML技术
用自己的语言说出,为什么需要XML?
XML提供了一种比较简单的描述内容的方法,而且这种方法能表述列表、树等常见的数据结构,可扩展性好。XML使用纯文本方法书写,人们可以读懂内容,也可以自行修改里面的内容。XML是树形的结构,关于树,有非常非常多很成熟的算法进行描述、操作、生成、分析,使得XML描述的数据可以很方便的生成和处理。
用自己的话描述XML有什么作用?
同上题。
XML文件的基本语法要求有哪些?
格式良好的XML文档需要满足:
必须有XML文档的声明语句;
必须有且仅有一个根元素;
标签成对出现;
标签名称大小写敏感;
属性值用双引号;
元素正确嵌套。
下面的XML代码有什么问题,请指出:
没有xml文档声明,如:
没有根元素;
属性值没有双引号,
标签名称大小写敏感,
【上机】完成课堂代码:
【上机】如下信息,能不能用JSON来表示?能不能用XML表示?请写出代码。
“我叫高小七,今年18了,我喜欢如花姑娘,也喜欢我的宠物旺财”
personalinfo>
【上机】CDATA有什么作用?写出测试代码
CDATA的作用:XML文档中的所有文本均会被解析器解析,只有CDATA区段中的文本会被解析器忽略。
实例:
xml解析器通常会解析xml文档中的所有文本。
当某个xml元素被解析时,其标签之间的文本也会被解析,如:
解析器之所以这么做是因为 XML 元素可包含其他元素,就像这个实例中,其中的
而解析器会把它分解为像这样的子元素:
但是,在实际应用中有这样一种情形:“name”标签之间的内容不需要被解析成子元素,而是整体作为“name”标签的内容,也就是“name”标签的字符数据,这个时候,就需要加CDATA标记,如下:
Bill
]]>< /name>
这样”name”之间的内容就不会被解析了(虽然它包含<,>等标签语法),而是全部当作字符(文本)数据来处理。CDATA表示“字符数据”(CharacterData)。
dtd技术有什么作用? schema技术什么作用?二者之间有什么关系?
在xml技术里,我们可以编写一个文档来约束某一个xml文档的书写规范,如一个xml文档要包含哪些元素,元素与元素之间的嵌套关系,某些元素必须具备哪些属性等,这称为xml约束。
常用的xml约束技术有两种:dtd和schema。
dtd:document type definition, 文档类型定义。近几年来XML技术领域所使用的最广泛的一种模式。但是它有其局限性:不能完全满足XML自动化处理的要求,例如不能很好实现应用程序不同模块间的相互协调,缺乏对文档结构、属性、数据类型等约束的足够描述等等。所以W3C于2001年5月正式推荐XML Schema为XML 的标准模式。显然,W3C希望以XML Schema来作为XML模式描述语言的主流,并逐渐代替XML DTD。XML Schema与XML DTD相比到底有哪些优势呢?
DTD 的局限性 DTD不遵守XML语法(写XML文档实例时候用一种语法,写DTD的时候用另外一种语法) DTD数据类型有限(与数据库数据类型不一致) DTD不可扩展 DTD不支持命名空间(命名冲突)
Schema的新特性 Schema基于XML语法 Schema可以用能处理XML文档的工具处理 Schema大大扩充了数据类型,可以自定义数据类型 Schema支持元素的继承Schema支持属性组
Schema支持命名空间(命名冲突)
xsl技术是做什么的?
XSL(eXtensible Stylesheet Language)是可扩展样式表语言的外语缩写,是一种用于以可读格式呈现 XML(标准通用标记语言的子集)数据的语言。
XML解析中,请说出DOM和SAX的区别。
DOM:
基于XML树结构
比较耗资源
适用于多次访问XML
SAX:
基于事件
消耗资源小
适用于数据量较大的XML
【上机】使用JDOM解析XML文档。参考老师课堂代码。
JDOM是一种解析XML的Java工具包。
JDOM和DOM的区别:
DOM适合于当今流行的各种语言,包括Java,JavaScripte,VB,VBScript,Perl,C,C++等。它了为HTML和XML文档提供了一个可应用于不同平台的编程接口。W3C DOM的最新信息可从http://www.w3.org/TR2001/WD-DOM-Lever-3-Core-20010913查阅。
DOM的设计为了适用于不同的语言,它保留了不同语言中非常相似的API。但是它并不适合于Java编程者的习惯。而JDOM作为一种轻量级API被制定,它最核心的要求是以Java为中心,只适合于Java语言,它遵循DOM的接口主要规则,除去了DOM中为了兼容各语言而与Java习惯的不同。
代码示例:
要处理的XML文档:
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
public class JDOMParse {
public static void main(String[] args) throws JDOMException, IOException {
//使用JDOM首先要指定使用什么解析器;
SAXBuilder sb=new SAXBuilder();
File file=new File("e:\books.xml");
//得到Document,我们以后要进行的所有操作都是对这个Document操作的:这个//Document类是org.jdom2.Document;
Document document=sb.build(file);
//得到根元素;在JDOM中所有的节点都是一个org.jdom.Element类,当然他的子节点
//也是一个org.jdom.Element类;
Element root=document.getRootElement();
//得到元素(节点)的集合;这表示得到“books”元素的所在名称为“book”的元素,
//并把这些元素都放到一个List集合中;
List bookList=root.getChildren("book");
//遍历List集合;
for(int i=0;i
//取得元素的子元素的值:
String title=book.getChildText("title");
String price=book.getChildText("price");
System.out.println("第"+(i+1)+"本书:"+title+""+price);
}
}
}
【上机】使用XPATH读取XML文档,测试各种XPATH。
XPath(XML Path Language)即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。
代码示例:
要处理的XML文档:
public class XPathTest {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerException, XPathExpressionException {
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
Document document=db.parse("e:\books.xml");
// 创建XPath对象;
XPath xPath=XPathFactory.newInstance().newXPath();
//获取根结点;
Node root=(Node)xPath.evaluate("//", document,XPathConstants.NODE);
System.out.println(root);
System.out.println(root.getNodeName());
//获取子元素并打印;
NodeList nodeList=(NodeList)xPath.evaluate("/books/", document, XPathConstants.NODESET);
for(int i=0;i
}
//只获取元素名称为"title"的元素;
NodeList nodeList1=(NodeList)xPath.evaluate("//*[name()='title']", document, XPathConstants.NODESET);
for(int i=0;i
XPath非常类似对数据库操作的SQL语言,或者说JQuery,它可以方便开发者抓起文档中需要的东西。
注:以上代码只是简单实例,详细学习请参照API。
【上机】jQuery中,如何解析xml文档。建立项目,测试之。
反射
什么情况下需要使用反射?
在编译时无法知道该对象或类属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。此时用反射。
Class类的作用及其主要功能?
我们说类是对象的设计图,像User类,Person类,Student类,每个类可以创建多个对象。而Class类是谁的设计图呢?Class类是类的设计图?也就是说,User类,Person类,Student类等每个类都是一个Class类的实例,在运行时都对应着一个Class对象。
Class类提供了很多方法,比如反射技术常用到的Class.forName("包.类(如User类)");这样可以获取User类的Class对象。通过这个Class对象,我们可以调用User类的方法,属性,构造方法等。
如何使用反射创建一个对象?
方法一:使用Class的newInstance()方法,仅适用于无参构造方法;
示例代码:
Class
User u=clazz.newInstance();
方法二:调用Constructor的newInstance()方法,适用所有构造方法;
示例代码:
Class
Constructor
User u= cons.newInstance( 1001,19,"王一一","男");
如何使用反射操作属性?
操作属性基本步骤:
通过Class对象获取Field(属性)对象;
调用Field对象的方法操作属性;
代码示例:
Class
//获得User类里属性名为”name”的属性并将其封装成一个Field对象name,接下来可//以用name调用Field的方法来操作属性;(略)
Field name=clazz.getField(“name”);
通过Class对象获得属性的方法有:
获取public的属性:object.getFields()
获取所有的属性: object.getDeclaredFields()
根据属性名称获取public的属性信息: object.getField(“sex”);
根据属性名称获取属性的信息:object.getDeclaredField(“name”);
如何使用反射执行方法?
调用方法基本步骤:
1.通过Class对象获取Method 对象;
2.调用Method对象的invoke()方法;
代码示例:
Class
User u=clazz.newInstance();
Method m2=clazz.getDeclaredMethod("show", String.class);
Object o=m2.invoke(u, "大家好");
System.out.println(o);
反射的优缺点有哪些?
优点:
反射提高了Java程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
反射是其它一些常用语言,如C、C++、Fortran 或者Pascal等都不具备的。
Java反射技术应用领域很广,如软件测试、 EJB、JavaBean等。
许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术。
缺点:
性能问题:
使用反射基本上是一种解释操作,字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
使用反射会模糊程序内部逻辑:
程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
【上机】使用反射模拟请求调用不同的Servlet实例。
正则表达式(自学)
正则表达式是用来做什么的?用自己的话描述。
正则表达式是用来操作字符串的,即用一些特定的符号来表示一些代码操作,从而简化对字符串的复杂操作。换句话说,用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。
说出下面规则的含义:
\d,\w,\s,.,[1234],[^a-f],{},?,+,*,\b
\d : 数字:[0-9];
\w: 单词字符:[a-zA-Z_0-9];
\s: 空白字符:[ \t\n\x0B\f\r];空格、水平制表符、换行、垂直制表符、换页、回车等。
.:任何字符。
[1234]:字符串长度为1,值为1、2、3、4中的一个数字;
[^a-f] :字符串长度为1,值为除了a-f的其它字符;
{}:匹配长度,如 \s{3} 表示匹配三个空白字符;
?:它前面相邻的字符重复0或1次;
+:它前面相邻的字符重复1到多次;
*:它前面相邻的字符重复0到多次;
\b:单词边界。匹配的是一个位置而不是字符,这个位置的一侧是构成单词的字符,另一侧是非单词字符、字符串的开始或结束位置。
分别说出在单行模式和多行模式下,他们的含义:
^ab, ab$;
先介绍一下多行模式和单行模式的概念:
多行模式:
^ 可以匹配字符串开头(字符串的开始位置),也可以匹配行的开头(即换行符\n之后的位置)$ 可以匹配字符串结尾(字符串的结束位置), 也可以匹配行的结尾(即换行符\n之前的位置)
单行模式:
^ 只能匹配字符串开头$ 只能匹配字符串结尾
注意这里有一个知识点:\r为回车符,\n 为换行符。在windows中,我们平常说的换行,实质上是先回车,后换行。
还是来看例子吧,以本题中的^ab , ab$为例:
String str="ab\nab\nab\n";
String reg="^ab";//默认是单行模式;
//String reg=”(?m)^ab”; 这个是多行模式,需要加(?m),m是”multiLine”的缩写。
Pattern p=Pattern.compile(reg);
Matcher m=p.matcher(str);
while(m.find()){
System.out.println(m.group());
System.out.println(m.start()+""+m.end());
}
单行模式时:无输出,也就是没有匹配的字符串。因为单行模式时从头到尾地匹配,字符串"ab\nab\nab\n"和正则表达式"^ab"是不匹配的。
多行模式时:
ab
0 2
ab
3 5
ab
6 8
因为多行模式是从字符串开始匹配到换行符(\n)之前,接下来从\n之后重新匹配再到下一个\n之前(或字符串结束)。字符串"ab\nab\nab\n"中有3个”\n”,每两个”\n”之间的字符都与正则表达式"^ab"匹配,所以输出以上结果。
单行,多行模式,都是正则表达式的模式修饰符里面出现的参数。
单行跟多行是冲突的,一次只能指定一个选项,不能同时使用
贪婪模式和非贪婪模式的区别是? 并说出如何使用贪婪模式、如何使用非贪婪模式。
1.什么是正则表达式的贪婪与非贪婪匹配
如:String str="abcaxc";
Patter p="abc";
贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(abc)。
非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(abc)。
2.编程中如何区分两种模式
默认是贪婪模式;在量词后面直接加上一个问号?就是非贪婪模式。
量词:{m,n}:m到n个
:任意多个
+:一个到多个
?:0或一个
\D,\d分别表示什么意思?
\d:数字[0-9];
\D:非数字[^0-9];
说明反向引用是什么意思?
(1)捕获组捕获到的内容,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。要了解反向引用,首先要了解捕获组,关于捕获组,请参考相关资料。
(2)捕获组(Expression)在匹配成功时,会将子表达式匹配到的内容,保存到内存中一个以数字编号的组里,可以简单的认为是对一个局部变量进行了赋值,这时就可以通过反向引用方式,引用这个局部变量的值。一个捕获组(Expression)在匹配成功之前,它的内容可以是不确定的,一旦匹配成功,它的内容就确定了,反向引用的内容也就是确定的了。(3)反向引用必然要与捕获组一同使用的,如果没有捕获组,而使用了反向引用的语法,不同语言的处理方式不一致,有的语言会抛异常,有的语言会当作普通的转义处理。
(4)示例说明:
源字符串:abcdebbcde
正则表达式:([ab])\1,这里的”\1”就是反向引用。
对于正则表达式“([ab])\1”,捕获组中的子表达式“[ab]”虽然可以匹配“a”或者“b”,但是捕获组一旦匹配成功,反向引用的内容也就确定了。如果捕获组匹配到“a”,那么反向引用也就只能匹配“a”,同理,如果捕获组匹配到的是“b”,那么反向引用也就只能匹配“b”。由于后面反向引用“\1”的限制,要求必须是两个相同的字符,在这里也就是“aa”或者“bb”才能匹配成功。
说明预搜索的含义?用自己的语言描述。
预搜索是用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ < > 这样的锚定作用,仅仅用于指定一个位置,不参与内容匹配。
还是来用例子说话吧:
(1)正则表达式:(?<=src=").?(?="), "表示转义,即双引号"
其中(?<=)为反向预搜索,表示要匹配的字符串前面必须是src="
(?=)为正向预搜索,表示要匹配的字符串后面必须是"
.?表示要匹配的内容
(2)用上例来匹配以下文本:
待测试的文本:
那么执行这个正则表达式后,就可以提取出/UploadFiles/image/20140304/20140304094318_2971.png
预搜索的语法:
(?=xxx)
正向预搜索(向右)
正向预搜索,判断当前位置右侧是否能匹配指定表达式
(?!xxx)
正向预搜索否定,判断当前位置右侧是否不能够匹配指定表达式
(?<=xxx)
反向预搜索(向左)
反向预搜索,判断当前位置左侧是否能够匹配指定表达式
(? 反向预搜索否定,判断当前位置左侧是否不能够匹配指定表达式
预搜索分两种,一种是向右,另外一种是向左。
【上机】完成电子邮件的表达式
根据对电子邮箱格式要求的不同所得的正则表达式也是不同的。下例写得有点复杂,仅做参考:
/^a-z@([a-z0-9][-_]?[a-z0-9]+)+[.][a-z]{2,3}([.][a-z]{2})?$/i
解释:
/内容/i: 构成一个不区分大小写的正则表达式;^ 匹配开始;$ 匹配结束。②[a-z]: E-Mail前缀必需是一个英文字母开头③([a-z0-9][-_]?[a-z0-9]+) :和a_2、aaa11、1_a_2匹配,和a1、aaff_33a、a__aa不匹配,如果是空字符,也是匹配的,表示0个或者多个。④表示0个或多个前面的字符.⑤[a-z0-9]* :匹配0个或多个英文字母或者数字;[-]? 匹配0个或1“-”,因为“-”不能连续出现。⑥[a-z0-9]+: 匹配1个或多个英文字母或者数字,因为“-”不能做为结尾⑦@: 必需有个有@⑧([a-z0-9]*[-]?[a-z0-9]+)+ :见上面([a-z0-9][-_]?[a-z0-9]+)解释,但是不能为空,+表示一个或者为多个。⑨[.]: 将特殊字符(.)当成普通字符;[a-z]{2,3} 匹配2个至3个英文字母,一般为com或者net等。⑩([.][a-z]{2})? :匹配0个或者1个[.][a-z]{2}(比如.cn等) 我不确定一般.com.cn最后部份是不是都是两位的,如果不是请修改{2}为{起始字数,结束字数} 。
【上机】完成电话号码和手机号码的表达式。
验证手机号码:13XXXX,15XXXX,18XXX开头的手机号码:
String tel="13900098900";
String telReg="1[358]\d{9}";
System.out.println(tel.matches(telReg));
【上机】完成获取一个HTML元素的表达式。
【上机】完成163网页中所有的图片url地址的表达式。
【上机】完成如下测试代码:
说出:group(),group(1),group(2)的区别。
group(int index)的参数和所匹配正则表达式的分组有关。Index就是正则表达式中组的编号(第几组)。group()和group(0)都是指的整个串,group(1) 指的是第一组的内容,group(2)指的第二组的内容。
代码示例:
String str = "Hello,World! in Java.";
Pattern pattern = Pattern.compile("W(or)(ld!)");//对正则表达式进行分组
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
System.out.println("Group 0:"+matcher.group(0));//得到第0组——整个匹配
System.out.println("Group 1:"+matcher.group(1));//得到第一组匹配——与(or)匹配的
System.out.println("Group 2:"+matcher.group(2));//得到第二组匹配——与(ld!)匹配的,组也就是子表达式
}
结果:
Group 0:World!
Group 1:or
Group 2:ld!
【上机】Javascript中,正则对象的test方法如何使用?写出测试代码。
【上机】Javascript中,字符串的match、split、replace方法,如何使用?写出代码。
【上机】Javascript中,使用正则对象时,模式:i,g。分别指的是什么?
阶段项目课程6
【项目】采用模拟数据实现网页三级联动的功能及用户名是否已注册校验的功能
练习目标:
熟悉HTML5
熟悉JavaScript语言
熟悉jQuery技术
百大项目第一阶段:项目调研
按照《百大项目》要求,自选项目主题,按照指定格式,完成操作手册的编写。
完成操作手册内容讲解视频的录制。
Oracle和Mysql数据库技术
查资料,回答下面问题:
Oracle公司的诞生和发展
(1)1977年程序员埃里森和另外两名程序员创建了软件开发实验室(Software Development Laboratories)。
(2)1970年IBM的一名研究人员写了一篇名为《大型共享数据库的关系数据模型》的论文,埃里森3人受到这篇文章的启发,决定构建一种新型数据库,称为关系数据库系统(relational database system).
(3)他们的第一个项目是为美国政府做的,他们给它取名为”Oracle”,因为他们认为“Oracle”有“智慧之源”的意思,作为这个项目的名字很恰当。
(4)1978年,此软件开发试验室迁至硅谷。为了扩大影响力,让人们更加了解公司的业务范围,他们将公司的名字从“软件开发实验室”更名为“关系软件公司(Relation Software Inc,简称RSI)”。
(5)1979年RSI开发出第一款商用SQL数据库。
1982年从RSI更名为Oracle系统公司(Oracle System Coroperion)。
1983年Oracle开发出便携式的RDBMS(关系型数据库管理系统),这是第一款能在PC机,小型机和大型机上运行的便携式数据库。
1984年,年收入突破千万,业务扩张至奥地利、德国、日本、瑞典、瑞士。
1986年,公司上市,年收入达5,500美元。同年推出第一个客户端/服务器数据库。业务继续向全球扩张。
1987年,年收入过亿元。Oracle正式成为世界上最大的DBMS软件公司。它组建了由七个员工和两个产品组成的应用产品部,这标志着它开始进入企业应用产品市场。开始开展咨询和支持业务,旨在帮助客户更好地使用他们的软件。
现在,Oracle咨询部是世界上最大的咨询部之一。
1989年,年收入突破5亿元。建起了6座摩天大楼,试图营造自己的园区。
同年,Oracle在IBM大型机,DEC和Unix小型机以及OS/2 PC机上,创下了事物处理业绩的最佳纪录。
1991 年,年收入达到 10.28 亿美元。
Oracle中国公司正式在中国注册为“北京甲骨文软件系统有限公司”.
1992年,Oracle7数据库发布。
1993 年,年收入达到 15.03 亿美元。
1997年6月,ORACLE第八版发布。ORACLE8支持面向对象的开发及新的多媒体应用,这个版本也为支持Internet、网络计算等奠定了基础。同时这一版本开始具有同时处理大量用户和海量数据的特性。
1998年9月,ORACLE公司正式发布ORACLE 8i。“i”代表Internet,这一版本中添加了大量为支持Internet而设计的特性。这一版本为数据库用户提供了全方位的Java支持。ORACLE 8i成为第一个完全整合了本地Java运行时环境的数据库,用Java就可以编写ORACLE的存储过程。
在2001年6月的ORACLE OpenWorld大会中,ORACLE发布了ORACLE 9i。
2003年9月8日,旧金山举办的ORACLE World大会上,Ellison宣布下一代数据库产品为“ORACLE 10g”。ORACLE应用服务器10g(ORACLE Application Server 10g)也将作为甲骨文公司下一代应用基础架构软件集成套件。“g”代表“grid ,网格”。这一版的最大的特性就是加入了网格计算的功能。
2007年11月,Oracle 11g正式发布,功能上大大加强。11g是甲骨文公司30年来发布的最重要的数据库版本,根据用户的需求实现了信息生命周期管理(Information Lifecycle Management)等多项创新。
2009年,收购了SUN公司。
Oracle数据库安装后启动的几个服务都代表什么含义.我们一般启动哪几个服务即可?
共7个服务:
Oracle ORCL VSS Writer Service;手动启动;
描述:Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Service)能够让存储基础设备(如磁盘,阵列等)创建高保真的时间点映像,即映射拷贝。它可以在多卷或者单个卷上创建映射拷贝,同时不会影响到系统性能。
OracleDBConsoleorcl;默认自动启动;
描述:数据库控制台服务,orcl是Oracle的实例标识,默认是orcl。在运行Enterprise Manager(企业管理器OEM)时,需要启动这个服务。
OracleJobSchedulerORCL;默认自动禁止;
描述:Oracle作业调度(定时器)服务,ORCL是Oracle的实例标识,默认是ORCL,可以自定义。
OracleMTSRecoveryService;默认自动启动;
描述:服务器端设置。该服务允许数据库充当一个微软事务服务器MTS。
OracleOraDb11g_home1ClrAgent;手动启动;
描述:数据库.Net扩展服务的一部分。
OracleOraDb11g_home1TNSListener;默认自动启动;
描述:监听器是Oracle基于服务器端的一种网络服务,用于监听客户端向数据库服务器端发出的连接请求。只存在于服务器端,监听器的设置也是在服务器端设置的。
服务只有在数据库需要远程访问时才需要启动(无论是从另一台主机远程访问还是从本机通过SQL*Net网络协议进行访问都属于远程访问)。如果不开启这个服务就只能访问本地数据库。
OracleServiceORCL;默认自动启动;
描述:数据库(实例)服务,是Oracle的核心服务,是数据库启动的基础。只有该服务启动,数据库才能正常启动。
【上机】安装Oracle 数据库,并使用sqlplus和浏览器分别测试。
在DOS系统中(用cmd进入):键入命令sqlplus,实际调用的是Oracle的sqlplus工具。调用成功按要求输入数据库用户名和密码即可。
在浏览器中连接数据库:
http://localhost:1158/em
如果你只有一个Oracle实例,用1158端口是可以登录的。
如果有多个Oracle实例,登录不同的数据库需要对应不同的端口号。端口号查询:
查询地址为:你本地oracle服务器安装地址下:如D:\database_oracle_11g_install\product\11.2.0\dbhome_1\install\portlist.ini文件中。
使用Oracle自带的可视化工具sql developer;使用时需要配置使用的jdk的安装路径。
使用pl/sql可视化客户端工具访问Oracle数据库。
【上机】安装MySQL以及客户端软件navicat或者SQLyog,并建立连接测试。
Oracle中,查看某个表的结构使用哪个语句?
select table_name from user_tables: 获取当前用户的表(结构)
select table_name from all_tables:获取所有用户的表(结构)
select table_name from dba_tables:获取所有表包括系统表的表(结构)
Oracle中,select * from emp;表示什么含义?
查询表emp的所有行。
【上机】表是数据库中存储数据的基本单元。 ORM(Object relationship mapping对象关系映射)基本思想:
表定义了数据结构,类似于Java中的类。
字段定义了表的详细结构,类似于Java中类的属性。
记录(行)定义了某个数据,类似于Java中某个类的对象。
使用上面思路,将实验用表:emp和dept之间的关系,使用两个Java类表示。
emp表:
public class Emp{
private int empNo; //员工编号;
private String eName;//员工姓名;
private String job;//员工岗位;
private int mgr;//员工上级编号;
private String hireDate;//员工入职时间;
private double salary;//员工基本工资;
private double commit;//员工绩效;
private int depNo;//员工部门编号;
//构造方法,略;
//getter,setter方法,略;
}
dept表:
public class Dept{
private int deptNo; //部门编号;
private String dName; //部门名称;
private String loc;//部门地址;
//构造方法,略;
//getter,setter方法,略;
}
【上机】完成下面的sql语句,并截图表示出结果。
每个员工的所有信息
分析:把员工表的所有内容都列出来;
select * from emp;
每个人的部门编号,姓名,薪水
分析:这3项在一个表里吗?在,简单了。
同上题一样,也是14条纪录。把“”换成指定的列名。
select deptno,ename,sal from emp;
每个人的年薪
分析:还是查员工信息。没有“年薪”字段,但有”sal(月薪)”,可以通过计算得到年薪信息。
select ename,sal12 from emp;
计算23的值(利用虚拟表:dual)
select 23 from dual;
得到当前时间
select sysdate from dual;
求每个人的年薪,列的别名:“年薪”;
分析:怎么给列起别名呢?“as”关键字;
select ename,sal12 as 年薪 from emp;--“年薪”可以加或不加双引号,但单引号不行。
计算每个人的全年的收入包括月薪和年终津贴(使用:nvl函数处理null值)
分析:
年薪 是 (月薪+绩效)12;
但绩效(comm)有null值,当comm是null值时,月薪+绩效的结果也是null值;
所以,当comm为null值时,需要把它当作0来处理。哪个函数能胜此重任呢?nvl();
nvl()相当于一条if…else语句:如果字段值不为空,取原值;否则,空值当作0来处理。
select ename, sal*12+nvl(comm,0)as 年薪 from emp;
求姓名和薪水和津贴,格式为smith-sal-123(利用拼接字符串)
分析:拼接字符串不同于java中用“+”,这里用”||“。这里拼接的字符串是作为数据出现在字段内容中的。
select ename||'-'||sal||'-'||nvl(comm,0) 收入信息 from emp;
Oracle中,||表示什么含义?
字符串拼接。见上题“分析”部分。
Oracle中,双引号一般用于什么地方?单引号用于什么地方?
双引号:在给字段起别名时,双引号可以加在别名上(也可以不加);
如下例中的“年薪“:
select ename,sal*12 as “年薪” from emp;
单引号:
字段数据中需要拼接字符串时,字符串常量要加单引号。如下例中的连字符“-“:
select ename||'-'||sal||'-'||nvl(comm,0)from emp;
通过某varchar类型的字段数据值来查询记录时,这个用来查询的字段值要用单引号,如下例中的“KING“:
select * from emp where ename='KING';
【上机】完成下面的sql语句,并截图表示出结果。
求10这个部门的所有员工
分析:查员工信息;但只是查部分员工而不是全部员工的信息。那是哪部分员工呢?条件是:部门编号为10的员工。用where子句。员工表包含部门信息,所以还是单表查询。
select * from emp where deptno=10;
求名字是KING的这个人的信息
select * from emp where ename=’KING’;
求薪水大于2000的员工信息
select * from emp where sal>2000;
求部门不是10的员工信息
select * from emp where deptno<>10;
select * from emp where deptno!=10;
求薪水在800和1500之间的员工信息(包含800和1500)
select * from emp where sal between 800 and 1500;
列出deptno为10或者30,并且工资>2000的所有人
select * from emp where deptno in(10,30) and sal>2000;
利用in操作符,列出部门10和20的人员
select * from emp where deptno in (10,20);
利用like操作符,查询名字中含有"H"的人员
select * from emp where ename like '%H%';
分别利用like操作符和正则表达式,查询名字中含有"S"或者"M"的人员
select * from emp where ename like ‘%H%’or ename like‘%S%’;
下面两句话是否结果相同:相同。
select * from Emp where not ( deptno in(10,20));
select * from Emp where deptno not in(10,20);
数据库查询时,哪些内容区分大小写?哪些不区分?
sql语句关键字,如:select,from等不区分大小写;
表名和字段名:不区分大小写;
字段中的内容:区分大小写。
【上机】完成下面的sql语句,并截图表示出结果。
【上机】完成下面的sql语句,练习分组函数的使用,并截图表示出结果。
【上机】完成下面的sql语句,练习分组查询,groupby和having子句,并截图表示出结果。
下面的sql语句为什么不行?说出你的理由。
select ename,deptno,avg(sal) from emp group by deptno;
要查询的字段必须是单组分组函数和被分组的字段。此题中的”ename”既不是单组分组函数,也不是被分组的字段,所以报错。
说出:where、groupby、having、order by的执行顺序
执行顺序:where>group by>having>order by。
【上机】完成下面的sql语句,练习子查询,并截图表示出结果。
为什么需要对查询出的数据做分页处理?
在列表查询时由于数据量非常多,一次性查出来会非常慢;就算一次性查出来了,也不能一次性显示给客户端。所以要把数据分批查询出来,每页显示一定量的数据,这就是数据分页。
我们经常会碰到要取某次查询结果的n到m条纪录,这里也用到了分页思想。
说明Oracle数据库如何实现分页。
Oracle中的分页处理依赖于哪个字段? mysql中分页处理使用什么来实现?
Oracle : rownum;
Mysql : limit;
【上机】完成下面的sql语句,并截图表示出结果。
查询薪水最高的前5个人
select * from (select ename,sal from emp order by sal desc) where rownum<=5;
查询薪水排名(从高到低)在5-10之间的员工
select ename,sal,rn,rownum from (select t.*,rownum as rn from (select rownum, ename,sal from emp order by sal desc) t) ab where rn>5 and rn<=10;
为什么需要表连接? 常用的表连接查询有哪几种?分别适用于哪种情况?
数据库是由多张表组成的存储结构,并通过多张表之间的关系建立起完整有效的数据存储形式。为了获得多张表之间的完整有效的数据联系,数据库查询语言SQL提供了强大的表连接查询功能。表连接就是将多个表中的数据连接到一起的查询,即连接操作可以在一个select语句中完成从多个表中查询和处理数据的功能。
为什么需要笛卡尔积?笛卡尔积的作用是?
所谓笛卡尔积,通俗点说就是指两个集合中任意取出两个元素所构成的组合的集合。假设R中有元组M个,S中有元组N个,则R和S的笛卡尔积中包含的元组数量就是M*N.这个规则可以向多个关系扩展。
所有表连接方式都会先生成临时笛卡尔积表,表示两个表中的每一行数据任意组合。在实际应用中,笛卡尔积本身大多没有实际用处,只有在两个表连接时加上限制条件,才会有实际意义。
【上机】完成下面的sql语句,练习表连接,并截图表示出结果。
Oracle中, union和minus的作用。
Union: 是将两个或者两个以上的结果集合并在一起;
Minus: 是从一个结果集中减去一部分结果集。
Oracle中, union、 minus和intersect 的作用。
【上机】Oracle中,用minus的办法求薪水最高的第6到第10名雇员。
select * from ((select ename,sal,rownum from (select ename,sal,rownum as rn from emp order by sal desc) t where rownum<=10)
minus
(select ename,sal,rownum from (select ename,sal,rownum as rn2 fromemp order by sal desc) d where rownum<=5))
order by sal desc;
【上机】使用create table empCopy as Select * from emp;复制一张新表出来。
【上机】为新表增加记录,测试一下。
insert into empCopy values (7787,'amenda','secretary',7788,to_date('1988/04/08','YYYY/MM/DD'),3000,1500,10);
【上机】将新表中所有人的薪水翻番。
update empCopy set sal=sal*2;
【上机】将表中薪水大于5000的人全部删掉。
delete empCopy where sal>5000;
truncate和delete有什么区别?
TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:
二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。
TRUNCATE TABLE:删除内容不删除定义 , 释放空间。DELETE TABLE:删除内容不删除定义,不释放空间。
【上机】练习使用DML语句,完成如下一系列操作:
创建班级表:
id为主键
班级名称
班级成立时间
班级毕业时间
班级所在教室
create table sclass(
classid number not null primary key,
classname varchar(50) not null,
classstarttime date not null,
classgraduatetime date not null,
classroom varchar(50)not null
)
创建学生表:
建立一张用来存储学生信息的表,表中的字段包含了学生的学号、姓名、年龄、入学日期、年级、班级、email等信息,并且为grade指定了默认值为1,如果在插入数据时不指定grade得值,就代表是一年级的学生.
姓名不能为空。
email必须唯一,不能重复。
id为主键
classId作为外键关联到班级表的主键上。
create table STUDENT
(
STUID NUMBER not null,
SNAME VARCHAR2(20) not null,
AGE NUMBER,
SEX VARCHAR2(2),
ENTERDATE DATE,
CLASSID NUMBER,
GRADE VARCHAR2(50) default 1,
EMAIL VARCHAR2(50)
)
alter table STUDENT
add constraint PK_STUID primary key (STUID)
alter table STUDENT
add constraint UNIQUE_EMAIL unique (EMAIL)
alter table STUDENT
add constraint FK_CLASSID foreign key (CLASSID)
references CLASSGROUP (CLASSID);
增加2个班级
insert into sclass values(1,'百合班',to_date('2009/08/08','YYYY/MM/DD'),to_date('2012/08/08','YYYY/MM/DD'),'101');
insert into sclass values(2,'牵牛花班',to_date('2010/08/08','YYYY/MM/DD'),to_date('2013/08/08','YYYY/MM/DD'),'202');
增加4个学生,并且每个学生都放到相应班级里面
举例:
insert into student values(9,'赵照',22,'男',to_date('2010/08/09','YYYY/MM/DD'),2,1,'[email protected]');
insert into student values(10,'孙黎',22,'男',to_date('2010/08/09','YYYY/MM/DD'),2,1,'[email protected]');
如何删除其中某个班级
先要解除学生表中对班级的外键约束:
alter table STUDENT1
drop constraint FK_CLASSID1
删除某个班级,如:
delete sclass where classid=1;
为班级表增加新的字段:教室地址
alter table sclass
add address varchar(50)
删除学生表
drop table student
什么是事务?为什么需要事务?(查资料说明)
事务是指作为单个逻辑工作单元执行的一组相关操作,这些操作要求全部完成或者全部不完成。事务使使数据库从一种状态变换成为另一种状态,是数据库所特有的。
使用事务的原因:保证数据的安全有效。
说出事务的特点?
事务的特性有四个:简称ACID即 1、原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
2、一致性(Consistence):事务完成时,要使所有的数据都保持一致的状态,换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
3、隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
4、持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障, 也不应该丢失。
一个事务,什么时候开启?什么时候结束?
Oracle的事务开始于一个DML(数据库管理语句,如:create、drop、rename、alter)语句。当以下情况发生时,事务结束:1、COMMIT/ROLLBACK2、执行了DDL(数据库定义语句)/DCL(数据库控制语句)语句3、客户端主动断开数据库的连接(DISCONNECT)4、数据库关闭(宕机)另外,一个DDL/DCL语句实际上就是一个事务,其中隐含了COMMIT。Oracle不需要特别的去指定事务的开始和结束。一个事务的结束就是下一个事务的开始。
回退后,是不是指回退到事务执行前数据库的状态?
如果设置了savepoint,则回滚到上一个savepoint;如没设置savepoint,则回滚到事务执行前的状态。
简述事务提交和事务回退之后,数据库的状态。
事务没有提交。其他用户会不会看到事务的执行结果?
不会。
【上机】模仿老师课堂代码,做实验测试事务。
索引有什么作用?
索引是一种供服务器在表中快速查找一个行的数据库结构。合理使用索引能够大大提高数据库的运行效率,具体如下:
快速存取数据。(2)既可以改善数据库性能,又可以保证列值的唯一性。(3)实现表与表之间的参照完整性(4)在使用orderby、groupby子句进行数据检索时,利用索引可以减少排序和分组的时间。
数据库的索引是什么?为什么使用索引之后查询数据会很快?
什么字段适合做索引?什么字段不适合做索引?
应该建索引列的特点:
1) 在经常需要搜索的列上,可以加快搜索的速度;
2) 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
3) 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
4) 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
5) 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
6) 在经常使用在WHERE 子句中的列上面创建索引,加快条件的判断速度。
不应该建索引列的特点:
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
对于那些定义为blob数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
选取索引的字段有什么技巧,什么字段适合做索引?
【上机】针对emp表的ename创建索引。然后删除。
创建:create index index_on_emp on emp(ename);
删除:drop index index_on_emp;
序列也是一种数据库对象,不只Oracle有,其他数据库也有。
是oacle提供的用于产生一系列唯一数字的数据库对象。
简述序列的作用,并说明哪些数据库包含序列?
【上机】创建一个序列(初始值从1000开始,按照10递增). 然后,使用这个序列维护emp表的empno字段的值。
create sequence seq_emp
increment by 10
start with 1000
cache 20;
【上机】删除5题中创建的序列
drop sequence seq_emp;
列出视图的几个作用?
视图是什么?
视图只是一条select语句,并不会存储表对应数据。
查询视图就是查询表,添加视图就是向数据库表中添加数据。
视图作用
安全,只读,只操作部分行部分列。
简化操作。
解释说明什么叫做视图并说明视图的作用。
见上题。
【上机】使用视图重构下面的代码,以前的作业(求平均薪水的等级最低的部门)
添加创建视图的语句即可:
create view dname_with_lowest_sal_grade
as
select语句……(略)
Power Designer软件是用来做什么的?上网查询资料,说明这个软件的历史。
Power Designer的历史:
PowerDesigner最初由Xiao-Yun Wang(王晓昀)在SDP Technologies公司开发完成。在法国称为AMC*Designor,在国际市场上称为S-Designor。在这两个产品名字中都包含“or”,它实际上特指“Oracle”,因为在产品开发的最开始是为Oracle数据库设计的,但是很快就发展并支持市场上所有主流的数据库系统。SDP Technologies是一个建于1983年的法国公司,1995年,Powersoft公司购买了该公司,而在1994年早期,Sybase已经买下了Powersoft公司。在这些并购之后,为了保持Powersoft的产品商标的一致,改名叫做“PowerDesigner”。 目前Sybase拥有PowerDesigner及其法文版PowerAMC的所有权利。
Power Designer的功能:
Power Designer 是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型,还可以为数据仓库制作结构模型,也能对团队设计模型进行控制。他可以与许多流行的软件开发工具,例如PowerBuilder、Delphi、VB等相配合使开发时间缩短和使系统设计更优化。
power designer是能进行数据库设计的强大的软件,是一款开发人员常用的数据库建模工具。使用它可以分别从概念数据模型(Conceptual Data Model)和物理数据模型(Physical Data Model)两个层次对数据库进行设计。在这里,概念数据模型描述的是独立于数据库管理系统(DBMS)的实体定义和实体关系定义;物理数据模型是在概念数据模型的基础上针对目标数据库管理系统的具体化。
是否使用过Power Designer软件,在数据库设计阶段是如何使用的?
【上机】完成如下有关Power Designer的操作:
【上机】在navicat或SQLyog中建数据库:bjsxt,在这个数据库下建表: _class:id,班级名称,地址 _stu:id,name,classId(外键关联到_class表)
【上机】将上题中表的数据导出成sql文件,然后使用power designer的逆向 生成PDM图。
【上机】power designer中,使用mysql数据库时,主键自动递增怎么实现?
简述数据库的三大范式,并说明为什么在进行数据库设计的时候要遵循三范式?
范式的定义:是指导数据库设计的规范化理论,可以保证数据库设计质量
第一范式:
最基本的范式
数据库表每一列都是不可分割的基本数据项,同一列中不能有多个值
简单说就是要确保每列保持原子性(字段不能再分)
第二范式:
需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
即在一个数据库表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
简单说就是不存在局部依赖。
第三范式:
确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
属性不依赖于其他非主属性。
简单说就是不存在传递依赖(间接依赖) 。
范式的优缺点:
优点
结构合理
冗余较小
避免插入删除修改异常
缺点
性能降低:多表查询比单表查询速度慢
范式的应用特例:特定表的的设计可以违反第三范式,增加冗余提高性能
数据库设计中,一对多如何处理?
数据库外键关系表示的其实是一种一对多关系,所以处理一对多时可以使用外键。
数据库设计中,多对多一般如何处理?
引入中间表,把一个多对多表示为两个一对多。
数据库设计中,表跟表之间的关系有几种,如何处理表与表之间的关系?
阶段项目课程7
练习目标:
学会使用关系型数据库理念分析项目。
熟练使用PowerDesigner设计软件
熟练相关SQL语句
完成选课系统数据库设计(将设计好的PDM图截图):
设计百度知道的数据库结构,设计优酷视频网站的数据库结构。(二选一)
扩展
录制上个题目作业的讲解视频,讲解数据库设计方案。
百大项目第二阶段:数据库表设计
按照《百大项目》要求,完成初步的数据库表设计。
完成数据库表设计过程,讲解视频的录制。
存储过程
简要说明什么是PL/SQL
【上机】使用匿名块编写helloworld程序
简要说明常见的变量类型以及变量的声明规则
【上机】练习使用plsql操作异常处理过程
解释说明immediate的作用
简要说明plsql中的游标的作用
解释说明游标的分类以及游标的使用方法
创建存储过程的步骤
如何使用JDBC熟练调用存储过程
解释说明plsql中的触发器的作用
【上机】创建一个存储过程,以员工号为参数,输出该员工的工资
【上机】创建一个存储过程,以员工号为参数,修改该员工的工资。若该员工属于 10号部门,则工资增加150;若属于20号部门,则工资增加200;若属于30 号部门,则工资增加250; 若属于其他部门,则增加300。
【上机】创建一个存储过程,以员工号为参数,返回该员工的工作年限(以参数形 式返回)
【上机】创建一个存储过程,以部门号为参数,输出入职日期最早的10个员工信 息
【上机】创建一个函数,以部门号为参数,返回该部门的平均工资。
【上机】创建一个函数,以员工号为参数,返回该员工所在的部门的平均工资
【上机】创建一个存储过程,以员工号和部门号作为参数,修改员工所在的部门为 所输入的部门号.如果修改成功,则显示“员工由……号部门调入调入……号部门”; 如果不存在该员工,则显示“员工号不存在,请输入正确的员工号。”;如果不 存在该部门,则显示“该部门不存在,请输入正确的部门号。”。
【上机】创建一个存储过程,以一个整数为参数,输入工资最高的前几个(参数值) 员工的信息
【上机】创建一个存储过程,以两个整数为参数,输出工资排序在两个参数之间的 员工信息
【上机】用三种方式实现循环控制要求使用loop,要求有一个变量iCount,循环 前给变量赋值为0,每循环一次就加2,当变量为100的时候就退出循环
【上机】写出下面的循环控制,要求使用for处理。假设:已经存在一个变量 iCount 要求1: 循环前要先给变量赋值为0,每循环一次就加2,当变量为100的时候,就 退出循环
【上机】1.定义三个变量v_ID和v_Name和v_Age ,前两个类型为字符,长度为20, 后面一个类型为数字,2.定义一个游边EMP_INFO,通过表[员工]来取字段 [ID],[NAME],[AGE]的员工信息3.遍历取到的员工信息,分别把值取出来赋给 定义的变量
【上机】假设已经存在一个变量v_Counter,类型为字符存在一个变量v_Flag,类型 为字符当v_Counter=1时,v_Flag赋值为1当v_Counter=2时,v_Flag赋值为2, 当不是以上的情况时候,什么都不做.
JDBC技术
JDBC全称是什么?
JDBC:Java DataBase Connectivity,Java数据库连接。
请详细说明JDBC技术主要用于处理什么问题,有什么好处?
JDBC是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问。 它由一组由Java语言编写的类和接口组成。
有了JDBC,程序员只需用JDBC API 写一个程序,就可以访问所有的数据库。
将Java语言和JDBC结合起来,使程序员不必为不同的平台写不同的应用程序,只需写一遍程序就可以使它在任意平台上运行,这也是Java语言“一次编写,到处运行”的优势。
简单地说,JDBC可以做三件事:与数据库建立连接,发送、处理数据库语句并处理结果。
Class.forName("Oracle.jdbc.driver.OracleDriver"); 的作用是? 并简述其底 层原理。
加载Oracle的JDBC驱动程序。
JDBC中执行DML语句时,一般使用哪个方法较好:execute、executeQuery, executeUpdate。并说出这几个方法的区别。
见533题。
JDBC中执行DML语句时有三种方法,请说明是哪三种方法并简述三种方法的适 用场景。
见533题。
解释下面三个方法返回值的含义:
execute、executeQuery,executeUpdate
executeQuery:返回结果集(ResultSet),通常用于select语句。
executeUpdate:返回此操作影响的行数(int),通常用于insert, update, delete语句。
execute:返回布尔值(boolean),通常用于insert,update,delete语句。
【上机】用文字说明ResultSet处理的典型代码各行的作用:
并解释,getString(1)的含义。 getInt("empno")的含义。
详述JDBC编程的4大步骤?
1:加载一个Driver驱动。
2:创建数据库连接(Connection)。
3:创建SQL命令发送器Statement ;通过Statement发送SQL命令并得到结果。
4:处理结果(select语句和ResultSet);处理完毕后关闭数据库资源 。
大对象的作用。
大对象LOB(Large Object)是一种数据库数据类型,用来存储大数据量数据,如音频和图像等。
Oracle里有两种使用方法:
存储在数据库里,参与数据库的事务。有三种是这个大对象:BLOB, CLOB , NCLOB。
存储在数据库外的一种:BFILE ,不参与数据库的事务,也就是不能roolback 或者commit等,它依赖于文件系统的数据完整性。
(3)简单的代码示例:创建一个包含大对象数据类型的表;
CREATE TABLE waterfalls ( falls_name VARCHAR2(80),--name falls_photo BLOB,--照片 falls_directions CLOB,--文字 falls_description NCLOB,--文字 falls_web_page BFILE);--指向外部的html页面
请简述数据库中大对象的类型及作用,并说明JDBC访问大对象的流程。
【上机】SQL注入攻击是怎么回事?用代码说明。
例如:使用JDBC完成用户的登录功能:
(1) SQL语句采用了字符串拼接String sql="select * from t_user where userno='"+userno+"' and password='"+upwd+"'";
(2) 继而使用SQL命令发送器发送SQL命令并得到结果:stmt.executeQuery(sql);
(3) 如输入:userno=”abc”,password=”abc ‘or’1’=1”;
那上述sql字符串就变成:sql=”select * from t_user where userno=’abc’ and password=’abc ‘ or ’1’=’1’”;
这条语句中的用户名和密码并不正确,但仍然能访问数据表,所以存在风险。这就是SQL注入攻击。
(4) 解决方案:采用Statement的子接口PreparedStatement来实现, PreparedStatement的优点:
*1.可读性性强不繁琐。
*2.安全。
*3.多次执行同一条sql语句,效率高。
【上机】完成对Oracle数据库的查询操作,将emp表中所有的数据列出。
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
stmt=conn.createStatement();
String sql="select * from emp";
rs=stmt.executeQuery(sql);
int empNo=0;
String eName=null;
String job=null;
int mgr=0;
Date date=null;
String hireDate=null;
float salary=0;
float comm=0;
int deptNo=0;
while(rs.next()){
empNo=rs.getInt(1);
eName=rs.getString(2);
job=rs.getString(3);
mgr=rs.getInt(4);
date=rs.getDate(5);
hireDate=new SimpleDateFormat("YYYY/MM/DD").format(date);
salary=rs.getFloat(6);
comm=rs.getFloat(7);
deptNo=rs.getInt(8); System.out.println(empNo+"\t"+eName+"\t"+job+"\t\t"+mgr+"\t"+hireDate+"\t"+salary+"\t"+comm+"\t"+deptNo);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
【上机】完成对Oracle数据库的删除操作,将sal小于1500 的记录删除。
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
stmt=conn.createStatement();
String sql="delete from emp where sal<1500";
System.out.println(stmt.executeUpdate(sql));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
PreparedStatement(预编译SQL语句)有什么优势?
PreparedStatement 接口继承 Statement接口
如果需要多次执行一个SQL语句,可以使用PreparedStatement对象。在创建PreparedStatement对象时,通过传递不同参数值多次执行PreparedStatement对象,可以得到多个不同的结果。
优势:执行效率高、代码可读性强、安全性高
【上机】完成老师课堂上测试PreparedStatement的代码
【上机】JDBC中,事务是如何管理的?使用代码说明。
在JDBC中,事务操作缺省是自动提交。
一条对数据库的更新表达式代表一项事务操作
操作成功后,系统将自动调用commit()提交,否则调用rollback()回滚
在JDBC中,事务操作方法都位于接口java.sql.Connection中
可以通过调用setAutoCommit(false)来禁止自动提交。
之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用 commit()来进行整体提交,
倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响 应的异常;
此时就可以在异常捕获时调用rollback()进行回滚,回复至数据初始状态
事务结束的边界是commit或者rollback方法的调用
事务开始的边界则不是那么明显了,它会开始于组成当前事务的所有statement中的第一个被执行的时候。
以下是代码:
try {
stmt = conn.createStatement();
conn.setAutoCommit(false);
String sql1 ="update account set balance = balance-1000 where aid=1";
String sql2 ="update account set balance = balance+1000 where aid=2";
stmt.executeUpdate(sql1);
stmt.executeUpdate(sql2);
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
【上机】通过资源文件的方式,将相关数据库信息放入资源文件中。使用代码说明。
JDBC(Java DataBase Connectivity:Java数据库连接)有多种方式,其中一种是通过从资源文件读取加载方式来连接数据库。
JDBC最常用的资源文件类是Properties.
步骤是:
首先要创建一个文本文件,以.properties后缀名结尾,如db.properties.
以“键=值”的方式书写一个属性的配置信息,如:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/student
db.username=root
db.password=root
代码示例:
创建一个DbUtil.java类:
public class DbUtil{
//数据库驱动
privatestatic String Driver="";
//数据库地址
privatestatic String url="";
//数据库用户名
privatestatic String userName="";
//数据库密码
privatestatic String password="";
//创建static静态代码块,项目启动的时候就执行加载数据库连接的必要配置文件信息;
static {
Properties p=new Properties();
try {
//通过相对路径加载文件
p.load(new FileInputStream(new File("cof/Db.properties")));
//用getProperty方法通过关键字获取信息
Driver = p.getProperty("Driver");
url = p.getProperty("url");
userName = p.getProperty("userName");
password = p.getProperty("password");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建连接数据库的方法体;
public Connection getConn(){
Connection conn=null;
try {
//加载驱动
Class.forName(Driver);
//获取数据库连接
conn=DriverManager.getConnection(url,userName,password);
}
catch (SQLException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e){
e.printStackTrace();
}
return conn;
}
}
测试:
publicclass TestDbutil {
publicstaticvoidmain(String[] args) {
//new一个DbUtil对象从而得到连接数据库的方法
DbUtil util = new DbUtil();
Connection conn = util.getConn();
//上面两条代码已经通过读取资源文件的方式建立了数据库连接,接下来就//可以按常规操作数据库了(此处略)
//操作完数据库关闭资源(略)
通过读取资源文件来创建数据库连接的好处:
以文件读取加载方式连接数据库,这种方式的好处在于当数据库驱动,地址或者用户名密码发生变动时,只需要在文件里改动即可,而不需要在代码里改动,这也很好体现了代码的封装性原则。
【上机】JDBC的批处理如何完成,写出课堂代码。
需要向数据库发送多条sql语句时, 为了提升执行效率, 可以采用JDBC的批处理机制。
JDBC的批处理机制主要有:Statement或PreparedStatement对象及以下方法:
addBatch(String sql) :Statement类的方法, 多次调用该方法可以将多条sql语句添加到Statement对象的命令列表中。执行批处理时将一次性的把这些sql语句发送给数据库进行处理。
addBatch(): PreparedStatement类的方法, 多次调用该方法可以将多条预编译的sql语句添加到PreparedStatement对象的命令列表中。执行批处理时将一次性的把这些sql语句发送给数据库进行处理。只能应用在类型相同参数不同的sql语句中, 此种形式的批处理经常用于在同一个表中批量插入数据, 或批量更新表的数据。
executeBatch():把Statement对象或PreparedStatement对象命令列表中的所有sql语句发送给数据库进行处理。
clearBatch(): 清空当前sql命令列表。
代码示例:
public class BatchTest {
public void statementBatch() {
Connection conn = null;
Statement st = null;
String sql_1 = "insert into student(name, age) values('李明', 24)";
String sql_2 = "insert into student (name, age) values('李然', 22)";
String sql_3 = "insert into student (name, age) values('王雷', 21)";
String sql_4 = "update student set name='张衡' where id=1";
try {
conn = JdbcUtils.getConnection();
st = conn.createStatement();
st.addBatch(sql_1);
st.addBatch(sql_2);
st.addBatch(sql_3);
st.addBatch(sql_4);
st.executeBatch();
st.clearBatch();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(null, st, conn);
}
}
public void preparedStatementBatch() {
Connection conn = null;
PreparedStatement st = null;
String sql = "insert into student (name, age) values(?, ?)";
try {
conn = JdbcUtils.getConnection();
//通过只打开一个连接 ;
st = conn.prepareStatement(sql);
for (int i = 0; i < 10; i++) {
st.setString(1, "SN_" +( i+1));
st.setInt(2, i+10);
st.addBatch();
// 需要防止Preparedstatement对象中的命令列表包含过多的待处理sql语句, 而造成outOfMemory错误
if (i % 5== 0) {
st.executeBatch();
st.clearBatch();
}
}
// 将剩下的未处理命令发送给数据库 ;
st.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(null, st, conn);
}
}
}
JDBC批处理的好处:
前期的代码在与数据库进行通信时,都是先建立连接,建立连接花费的成本是最高的,然后发一个SQL语句,执行完后就关闭了连接。还有一个问题是发送的SQL语句都是通过网络传送的,比起本地调用来说,网络传输的成本也是高很多的。如果要插入或者更新一批数据进数据库,还是采用前期的方法,花费的时间会很多,给用户的感受会很慢。但是如果采用批处理,则在两个方便都会节约大部分成本,速度会更快。
注意:不要一次性向命令列表中添加数量过多的sql语句, 防止出现outOfMemory错误。
【上机】JDBC控制访问存储过程。
阶段项目课程8
【项目】员工管理系统
练习目标:
熟练使用JDBC
使用DAO模式实现JDBC常用的CRUD操作
使用ORM思想封装JDBC常用的CRUD操作,提取BaseDao
要求:
根据老师课程讲解,完成对员工的各种操作。
扩展
【项目】自学apache commons中的JDBCUtils组件
HTML语言
互联网三大基石分别是什么?并阐述他们的作用。
HTML元素之间的关系有哪两种关系?并举例说明。
HTML中,属性值用双引号、单引号、不加引号都可以。这种说法对吗?
使用文本编辑器编辑完HTML后,扩展名需要使用哪些?
SEO是什么?title/description/keywords属性跟SEO是什么关系?
【上机】如何设计一个如下效果(URL前自定义一个图标)?
标记中alt属性和title属性有什么区别?
【上机】将youku上的某个视频通过