黑马程序员java培训就业班笔记:day09总结(共2篇)
黑马程序员java培训就业班笔记:day09总结 篇1
Day09总结: 上午:
1、final关键字:
Eg:代码实现:
Class Fu { Final void method(){
//code...访问低层代码
} } Class Zi extends Fu { Void method()
{
Sop(“haha”);} } 以上代码体现出继承的弊端,因为父类的method的方法访问了系统的低层代码。当子类对其覆写,就不会去访问父类的meth的方法,直接用自己的method这样就出现了代码的不严谨性,所以此时需要用final关键字进行修饰。注意为什么不把类加final修饰,因为可能该类中会出现很多功能。有些是不需要被覆写的。有些是被调用的。所以只能根据自己所需对相应的成员进行修饰。
2、Final的特点:
1、final是一个修饰符,可以修饰类、方法、变量(成员变量、局部变量)
2、Final修饰的类不可以被继承。
3、Final修饰的方法不可以被覆盖。
4、Final修饰的变量是一个常量,只能被赋值一次。是为了增强阅读性,只要数据是固定的,就将这个数据用一个名称来表示,并用final修饰。常量名称都是大写字母,多个单词组成时用下划线来分隔。
代码体现:
Eg:
Class Zi { Static final int num=90;//必须对变量进行初始化,不知道要最终化哪个值,所以必须对它进行初始化。加静态也是一样的,同样的道理,并且被初始化,此时静态和final没有必然的联系。当变量被final修饰时,说明变量已经是一个常量值,此时不能被修饰,可以用static来修饰。
Public stati double PI=3.14;Void method(){
Final int x=4;
X=8;
Sop(num);//既然是在操作一个固定的值。为什么不把4直接写在此处,如果这样做的的话,阅读性极差,你根本就不知道它所代表什么?为了增强阅读性,此时数据是不变化的,所以我们需要给它起个名字,并且用final来修饰。这样的话它也是固定的不变的。
注意:被final修饰的数值只能被覆写一次,并且修饰的常量名全部大写,多个单词组成时用下划线进行分隔。Eg:final int PERSON_AGE=4;} }
3、抽象类:
特点:
1、没有方法体的方法,称为抽象方法,必须存放在抽象方法类中,抽象方法和抽象类必须用abstract关键字来修饰,2、抽象类不可以被实例化,为什么?因为调用抽象方法没有意义?为什么?因为它连方法体都不存在?
3、抽象类必须由其子类将抽象类中的抽象方法都覆盖后,其子类才可以被实例化,否则该子类还是抽象类。Eg: Abstract class Demo { Abstract void show();} Class SubDemo extends Demo
Void show(){} //此时把父类中抽象方法覆盖,此时才能被实例化。} 比如水果,它就是抽象的,不具体它包含各种各样的水果,每种水果有它自己的体现。
抽象类涉及的问题?
1、抽象类中是否可以定义非抽象的方法?
可以 首先抽象类是一个类,类是用来描述事物,只不过描述事物过程中有些信息不具体,抽象类和一般类异同点:
相同:抽象类和一般类都用于描述事物,都可以定义成员。不同:抽象类中可以定义抽象成员函数,(抽象要么修饰类要么修饰函数)而一般类不可以。
抽象类不可以实例化,一般类可以实例化。
2、抽象类中是否有构造函数?
有,而且抽象类虽然自身不可以被实例化,但是其子类覆盖了所有的抽象方法后,是可以实例化的。所以抽象类的构造函数是用于给其子类对象进行实例化。
3、抽象类通常都是一个父类?
是、因为需要子类去覆盖父类中的抽象方法。代码体现:
Abstract class Demo{ Abstract voif show1();Abstract void show2();} Abstract class SubDemo extends Demo { Void show1();} Class Test extends SubDmeo { Void show2();}
4、抽象类中可不可以不定义抽象方法?
可以;看上去没有什么意义,其实有点意义,就是不让这个类创建对象,为什么不让创建? 代码体现:
interface InterTest//这是一个测试接口,有4种测试方式。
{ void test1();void test2();void test3();void test4();
} abstract class InterTestImpl implements InterTest//用这个类进行所有的空实现。但是创建对象是毫无意义的。所以用抽象。
{
public void test1(){}
public void test2(){}
public void test3(){}
public void test4(){} }
class Test2 extends InterTestImpl
{ public void test2(){}
}
class Test3 extends InterTestImpl
{ public void test3(){}
}
/*
class InterTestImpl implements InterTest
{
public void test2()//
{
sop(“testimpl test2”);
}
public void test1(){}//这样做实现太麻烦。代码重复。如何改进?
public void test3(){}
public void test4(){}
}
*/
5、抽象关键字 不可以和那些关键字共存?
Final:修饰了类是一个最终类,不可以被继承,然后abstract修饰的类必须是父类,需要被继承、冲突、非法的修饰符组合,abstract 和final Static:抽象方法被static修饰,就具备了可以被类名直接调用的的特点,但是抽象方法被调用没有意思。
Priavte:因为抽象方法被私有,无法被覆盖。
代码体现: 雇员实例:
需求:公司中程序员有姓名、工号、薪水、工作内容。
项目经理除了姓名、工号、薪水、还有奖金、工作内容
进行数据建模
做问题领域的分析就是找出问题领域的对象。
分析: 在这个问题领域中有两个对象: 程序员:
属性:姓名,工号,薪水
行为:工作内容 项目经理:
属性:姓名、工号、薪水、奖金
行为:工作内容。
这时候不能用项目经理去继承程序员。因为职能不同,但是有共性,只能抽取。
就有了员工:
属性:姓名,工号,薪水
行为:工作内容
*/ abstract class Employee
{ private String name;private String id;private double pay;Employee(String name,String id,double pay){
this.name=name;
this.id=id;
this.pay=pay;} public abstract void work();//工作内容是无法知道的。} class Programmer extends Employee { Programmer(String name,String id,double pay){
super(name,id,pay);} public void work(){
System.out.println(“code”);}
}
class Manager extends Employee { private double bonus;Manager(String name,String id,double pay){
super(name,id,pay);
this.bonus=bonus;} public void work(){
System.out.println(“manage”);} }
4、接口:
格式:interface{} 表现特点:
1、里面的方法都是抽象的。
2、接口中的成员都有固定的修饰符,最常见的成员:全局常量抽象方法。只是最常见,不代表只有它们没有其他的,全局常量,共有的不需要对象,直接用接口调用的,不可变的。
表现形式:Public static final
抽象方法:public abstract
3、接口的成员都是public的。
4、接口是不可以创建对象的。就相当于是抽象的特殊表达形式。(但是有区别和抽象类)
5、类与类之间是继承关系,类与接口之间是实现关系。
6、接口的出现可以多实现,避免了单继承的局限性。
7、一个类在继承一个类的同时,还可以实现多个接口、8、接口与接口之间是继承关系,而且可以多继承,以为接口的方法都没有主体。思想特点:
1、对外暴露的规则。
外设要介入计算机中,因为计算机外面提供了接口,这就是规则。
2、程序的功能扩展
3、降低了耦合性
4、用来多实现
结合电脑主板的思想进行阐述,它是个规则。对外提供的规则 它提高了我们功能的扩展性,降低了耦合性。主板和声卡:主板使用规则,声卡实现规则。
与抽象类的区别:抽象类有单继承的局限性,接口没有
5、java对多继承记住改良,以多现实接口的方式来体现。差别:多继承因为父类中有相功能时,会造成不确定性。为什么可以实现多实现?
因为继承中父类的方法有方法体?这才是造成不确定性的根本原因,而此处是没有方法体的。
代码体现:
interface A {
//int show();//这样是不可以的。无法覆盖。
void show();} interface B {
// void method();
void show();//当有重复的方法时。但是此时子类复写它是可以的,为什么?
//因为继承中父类的方法有方法体。这才是造成不确定性的根本原
因。而
//此处是没有方法体的。
} class C extends D implements A,B//多实现。此时c必须覆盖两个方法
{
public void show(){}
//public void method(){}
} //一个类在继承一个的类的时候还可实现多实现
class D
{
public void function();} //接口之间是可以继承,而且支持多继承。
interface InterA {
void showA();} interface InterB {
void showB();} interface InterC extends InterA,InterB//为什么此处可以实现多继承,因为方法没有主体。
{
void showC();}
class InterfaceDemo2
{
public static void main(String[] args)
{
C c=new C();
c.show();
System.out.println(“Hello World!”);
}
}
6、抽象类和接口之间的区别:
共性:它们都是不断抽取出来的抽象非概念
区别:
1、抽象类只能被单继承、接口可以被多实现,避免了单继承的局限性。
2、抽象类中可以定义抽象方法,和非抽象方法,它可以用于定义体系的基本共性的内容。接口中只能定义抽象方法,它主要用于对象的功能的扩展。
3、抽象类是继承关系,是is a关系,接口是实现关系是like a关系。
4、抽象类中的成员修饰符都是自定义的,接口中的修饰符都是固定的。记住:不要把接口狭义的理解为interface,应该理解广义些,就是对外提供的规则,凡是对外暴露的都可以是接口。
实现代码:
1、abstract class 犬
{ public abstract void 吃饭();
public abstract void 吼叫();
}
interface 搜爆
{ public void 搜爆();
}
class 搜爆犬 extends 犬 implements 搜爆//这是即具备了犬的基本特性,又具备了搜爆功能。
{ public void 搜爆(){} public void 吃饭(){}
public void 吼叫(){}
}
class 搜爆猫 extends 猫 implements 搜爆
{ public void 搜爆(){}
}
记住: 类里面都是定义的一些基础内容,接口里面都是定义一些特性内容,这样的方便了对其进行扩展。
//抽烟的学生,抽烟是额外功能。
2、abstract class Student
{ abstract void study();
}
interface Smoking
{ void smoke();
}
class SomkeStudent extends Student implements Smoking
{ public void study(){}
public void smoke(){}
}
//烟民。学生烟民 问题领域不同,对象的属性和行为也不同。
abstract class Somker
{
abstract void smoke();
}
interface Study
{ void study();
}
class StudentSmoker extends Smoker implements Study
{ public void smoke(){} public void study(){}
}
7、多态:重点掌握
定义:某一类事物的多种存在形态。代码实现:
class 动物
{}
class 猫 extends 动物
{
}
猫 x=new 猫();
动物 y=new 猫();//父类的引用变量指向了其子类的对象。
多态在代码中的体现,父类或者接口的引用指向了自己的子类对象。
实现代码:
class Animal
{ abstract void eat();
}
class Dog extends Animal
{ void eat(){
sop(“啃骨头”);} void lookHome()
{
sop(“看家”);}
}
class Cat extends Animal
{ void eat(){
sop(“吃鱼”);} void catchMouse(){
sop(“抓老鼠”);}
}
class Pig extends Animal
{ void eat(){
sop(“猪饲料”);} void gongdi(){
sop(“拱地”);}
} class DuoTaiDemo { public static void main(String[] args){
//Cat c=new Cat();
//c.eat();
//Cat c1=new Cat();
//c1.eat();
//method(c);
//method(c1);
重要知识点:----开发都用!
Animal a=new Cat();//此处猫对象类型自动向上提升---向上转型,当指向使用体系基本功能时,可以向上转型操作。
为什么体现多态性?
首先猫是一个实体,是一个猫类型,因为有了继承,是动物中的一种,把这个实体称之为动物也可以,所以它具备了两种形态,猫和动物。这便是体现了多态性。
//一旦向上转型,猫就不是猫了,已经是动物类型了。
a.catchMouse();//编译失败。
但是现在想执行猫的抓老鼠的功能怎么办?
向下转型:
Cat c=(Cat)a;//向下转型。当使用子类对象中的特有内容时,才做向下转型。
c.eat();
c.catchMouse();//此时是可以实现猫的抓老鼠的功能的。
总结:在多态转型中,至始至终只有子类对象做着类型的变化。
method(new Cat());
} public static void method(Animal a)//Animal a=new Cat();{
重点知识点:instanceof
if(a instanceof Cat)//对象instanceof 类型 判断具体对象是否是指定的类型。
{
Cat c=(Cat)a;//编译通过,但是不能运行,此时类型转换异常classCastException;
//此时为了程序的严谨性,需要对传入的的对象进行判断。
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog d=(Dog)a;
d.lookHome();
}
a.eat();
总结:
instanceof是一个关键字,用于判断对象的类型。什么时候用?
当进行向下转型时,先判断该对象是否符合被转成的子类型。
} }
8、重点理解:
1、多态的好处:提高了代码的扩展性,有了多态,前期设计好的内容可以使用后期出现的子类内容,对于指挥对象做事情这件事情,如果对象很多,指挥起来很麻烦,抽取对象的共性类型,对该类型的事物进行指挥就会变的很简单。
2、多态的前提:
1、必须要有关系:继承、实现。
2、必须有覆盖的操作。
3、多态的弊端:前期的程序虽然可以使用后期出现的子类内容,但是只能使用子类覆盖父类中的内容,不能使用子类中的特有内容。
黑马程序员java培训就业班笔记:day09总结 篇2
第1章 框架概述
什么是框架,为什么使用框架,框架优点
框架(framework)是一个基本概念上的结构,用于去解决或者处理复杂的问题
框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。框架是在特定的领域内解决问题。优点
重用代码大大增加,软件生产效率和质量也得到了提高
使用框架开发,它提供统一的标准,大大降低了我们的后期维护。学习框架重点:了解框架做了什么,我们要在这个基础上在做什么事情。
第2章 java开发中常用框架
SSH
(SSM SSI)SSH struts2 spring hibernate SSM(SSI)springmvc spring mybatis(ibatis)
SSH 它是企业开发中比较主流的一套架构。SSH框架在开发中所处的位置:
黑马程序员郑州中心 编著
第3章 Struts2框架介绍
什么是struts2框架,学习struts2框架的核心。
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互
Struts2=struts1+webwork
问题:struts2是一个mvc框架,它的mvc是什么?
javaweb开发中的mvc,是在jsp的model2模式中提过 Model------javabean View--------jsp Controller----servlet
黑马程序员郑州中心 编著
核心点: 1.拦截器 interceptor 2.Action 3.ognl与valueStack
在现在开发中与struts2比较类似的框架有哪些? Struts1 webwork springmvc jsf
Struts2框架流程
黑马程序员郑州中心 编著
第4章 今天内容介绍与重点
今天内容:
一个简单的登录案例
在这个案例中,我们要使用struts2框架怎样解决
重点: 1.struts2框架如何完成原来由servlet完成的工作。2.Struts2框架如何完成请求参数的封装处理 3.Struts2框架如何完成页面跳转。
黑马程序员郑州中心 编著
第5章 简单登录案例原型
需要三个jsp页面
login.jsp
success.jsp failer.jsp 还需要一个servlet
LoginServlet 主要完成的是业务逻辑操作。
login.jsp
LoginServlet
黑马程序员郑州中心 编著
第6章 Struts2框架来完成登录操作
6.1 问题:为什么使用struts2框架?
Struts2框架它是一个在web中应用的mvc框架。我们使用strtus2框架来完成web开发有什么优势?
6.2 问题:怎样使用strtuts2框架
首先要上网下载它的jar包。步骤: 1.导入相关的jar文件
2.需要在web.xml文件中配置一个Filter(只有配置了它才可以使用struts2框架)
黑马程序员郑州中心 编著
3.struts.xml配置
4.创建Action来完成逻辑操作
6.3 快速入门
我们使用的是struts2 2.3.24版本
我们使用strtus2框架不是直接将它的lib包下的所有的jar文件copy到项目中,而是使用其中的一部分。
我们可以参考它的示例代码:
1.导入13个jar包
2.需要在web.xml文件中配置StrutsPrepareAndExecuteFilter 3.创建一个struts.xml文件,它的位置是可以放置在src下。
黑马程序员郑州中心 编著
6.3.1 代码实现 6.3.1.1 jsp页面
6.3.1.2 Action
6.3.1.3 struts.xml文件配置
6.3.2 流程分析
黑马程序员郑州中心 编著
6.4 使用struts2完成简单登录操作
1.login.jsp页面不变动
2.创建一个LoginAction来完成逻辑操作 3.在struts.xml文件中完成配置操作
问题1:在LoginAction中如何得到username与password 可以直接在Action类中提供成员属性,并为其提供get/set方法。就可以得到请求参数
问题2:如果实现路径跳转?
1.我们可以给action中的方法添加一个String返回值
2.在struts.xml配置文件中,在其对应的action配置上通过
黑马程序员郑州中心 编著
第7章 Struts2框架执行流程
7.1 Struts2源码导入
对于struts2框架它的源代码我们主要使用三部分 1.struts2核心部分源代码
org.apache.struts2xx
srccoresrcmainjava
2.struts2的xwork核心部分源代码
srcxwork-coresrcmainjavacomopensymphonyxwork2 3.struts2的插件的源代码
srcplugins 7.2 关于struts.xml配置文件中提示问题
第一步
在eclipse的window下首选面中查找xml catalog 第二步
Location:配置本地的dtd文件路径 key type:选择URI
黑马程序员郑州中心 编著
Key: http://struts.apache.org/dtds/struts-2.3.dtd
注意版本要对应,如果你可以上网,那么会自动缓存dtd,具有提示功能。
7.3 执行流程介绍
1.当通过浏览器发送一个请求
2.会被StrutsPrepareAndExecuteFilter拦截
3.会调用strtus2框架默认的拦截器(interceptor)完成部分功能 4.在执行Action中操作
5.根据Action中方法的执行结果来选择来跳转页面Resutl视图
一般管StrutsPrepareAndExecuteFilter 叫做前端控制器(核心控制器),只有配置了这个filter我们的strtus2框架才能使用。
黑马程序员郑州中心 编著
Strtus2的默认拦截器(interceptor)它们是在struts-default.xml文件中配置 注意:这上xml文件是在strtus-core.jar包中。默认的拦截器是在defaultStack中定义的。
第8章 Struts2配置详解
8.1 Struts2配置文件加载顺序
第一个加载的是default.properties文件
位置:strtus2-core.jar包
org.apache.struts2包下 作用:主要是声明了struts2框架的常量
第二个加载的是一批配置文件
Strtus-default.xml 位置:struts2-corl.jar
作用:声明了interceptor result bean Strtus-plugin.xml 位置:在strtus2的插件包中 作用:主要用于插件的配置声明 Strtus.xml
黑马程序员郑州中心 编著
位置:在我们自己的工程中
作用:用于我们自己工程使用strtus2框架的配置 第三个加载的是自定义的strtus.properties 位置:都是在自己工程的src下 作用:定制常量 第四自定义配置提供
第五加载的是web.xml配置文件
主要是加载strtus2框架在web.xml文件中的相关配置.第六 bean相关配置
重点掌握: 1.Default.properties 2.Struts-default.xml 3.Struts-plugin.xml 4.Strtus.xml 5.web.xml
8.2 struts.xml文件配置介绍
8.2.1 package配置
1.name属性
作用:定义一个包的名称,它必须唯一。
黑马程序员郑州中心 编著
2.namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径
3.extends属性 作用:指定继承自哪个包。一般值是strtus-default strtus-default包是在strtus-default.xml文件中声明的。
4.abstruct属性 它代表当前包是一个抽象的,主要是用于被继承
8.2.2 action配置
1.name属性 作用:主要是与package的namespace联合使用来确定一个action的访问路 径
2.class属性
作用:用于指示当前的action类
3.method属性
作用:用于指示当前的action类中的哪个方法执行
8.2.3 result配置
它主要是用于指示结果视图
1.name属性 作用是与action类的method方法的返回值进行匹配,来确定跳转路径 2.type属性 作用是用于指定跳转方式
8.2.4 扩展
关于action配置中的class与method的默认值以及result中的name与type 默认值问题
原因:strtus-default.xml文件中配置
黑马程序员郑州中心 编著
它的作用就是当一个请求来时,如果查找不到指定的class及对应的method就会执行 ActionSupport类中的execute方法。
在这个类的execute方法中默认返回的是”success”
也就是说,result的name属性默认值是success,默认的跳转方式是请求转发 dispatcher
8.3 常量配置
default.properties文件中定义了struts2框架常用常量.问题:我们怎样可以定义常量
1.可以在src下创建一个strtus.properties配置文件 2.可以在web.xml文件中配置
3.可以直接在strtus.xml文件中定义常量(推荐)
注意:后加载的配置文件中的常量会将先加载的常量覆盖
第9章 Struts2的Action详解
Struts2中的action,主要是完成业务逻辑操作。Action替代在servlet中完成的作用。
黑马程序员郑州中心 编著
Action的学习主要有两点
1.如何创建一个struts2的action 2.如果访问一个struts2的action
1. Action类创建方式(三种)1.创建一个pojo类
Pojo(plani Ordinary java object)简单的java对象 Pojo类就是没有实现任何接口没有继承任何类 优点:无耦合
缺点:所有的功能都要自己完成
2.创建一个类实现一个Action接口
com.opensymphony.xwork2.Action
在Action接口中定义了五个常量,一个execute方法 五个常量:它们是默认的五个结果视图
INPUT: 它是struts2框架中interceptor中发现问题后会访问的一个视图 LOGIN:它是一个登录视图,可以在权限操作中使用
黑马程序员郑州中心 编著
NONE:它代表的是null,什么都不做(也不会做跳转操作)SUCCESS:这是一个成功视图 优点:耦合度低
缺点:还是需要自己来完成功能
3.创建一个类继承ActionSupport类
com.opensymphony.xwork2.ActionSupport ActionSupport类也实现了Action接口。我们在开发中一般会使用这种方案: 优点:具有丰富的功能,例如
表单校验 错误信息设置
国际化 缺点:耦合度高
9.1 action的访问方式
1.直接通过标签来配置,通过method来指定访问的方法,如果method没有,默认访问的是execute方法。
2.简化的action访问方式,可以使用*通配符来访问。
这种方式的缺点:不建议使用过多的*号,它带来程序阅读障碍,不便于理解 使用*来简化操作方案,它对名称规范必须进行一个统一。
黑马程序员郑州中心 编著
9.2 扩展--动态方法调用
这是strtus2提供的动态方法调用。
注意:对于strtus2的动态方法调用,要想使用我们必须配置一个常量来开启动态方法调用
这代表动态方法调用没有开启
黑马程序员郑州中心 编著
个人不建议使用动态方法调用
第10章 Struts2框架封装数据
主要解决的问题:是在action中如果获取请求参数
主要有两种方式: 1.属性驱动
a.直接在action类中提供与请求参数匹配属性,提供get/set方法
b.在action类中创始一个javaBean,对其提供get/set,在请求时页面上要进行修改,例如 user.username user.password ,要使用ognl表达式
以上两种方式的优缺点: 第一种比较简单,在实际操作我们需要将action的属性在赋值给模型(javaBean)去操作 第二种:不需要在直接将值给javaBean过程,因为直接将数据封装到了中。它要求在页面上必须使用ognl表达式,就存在页面不通用问题。javaBean
2.模型驱动
步骤: 1.让Action类要实现一个指定接口ModelDriven 2.实例化模型对象(就是要new出来javaBean)3.重写getModel方法将实例化的模型返回。
黑马程序员郑州中心 编著
对于模型驱动它与属性驱动对比,在实际开发中使用比较多,模型驱动缺点,它只能对
一个模型数据进行封装。
第11章 总结
今天主要内容是围绕着简单的登录案例来讲解: 1.关于strtus2框架的环境搭建 2.关于strtus2框架配置 3.关于strtus2框架请求参数封装 4.关于strtus2框架的路径跳转
关于action访问的配置
黑马程序员郑州中心 编著
namespace=””
extends=””>
class=””
method=””>
关于路径跳转问题: 是通过
默认值是dispatcher 它代表的是请求转发。针对于jsp页面 redirect 它代表的是重定向
针对于jsp页面
chain 它类似于请示转发,只不过它是针对于action跳转.redirectAction 它类似于重定向
针对于action 关于路径跳转的配置
可以直接在
下创建全局的result
黑马程序员郑州中心 编著
【黑马程序员java培训就业班笔记:day09总结】推荐阅读:
【黑马程序员】Java之debug总结三09-22
黑马程序员PHP培训教程:同步和异步介绍05-29
黑马程序员面试题精编06-01
黑马程序员基础测试题08-27
黑马程序员:AJAX入门系列10-17
黑马程序员济南中心PHP第11天教程11-12
【黑马程序员】为什么面试官喜欢问职业规划05-19
黑马程序员C语言教程:C++语言78个常见编译错误及分析11-15
好程序员学习笔记-Java网络07-10