admin 管理员组

文章数量: 887019


2024年2月26日发(作者:高压容器用什么计算)

第1章

一、问答题

1.Java有哪些特点?

Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。

Java语言是简单的。Java语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java。Java语言不使用指针,而是引用。并提供了垃圾回收机制,使得程序员不必为内存管理而担忧。

Java语言是纯粹面向对象的。Java语言提供类、接口和继承等。

Java语言是分布式的。Java语言支持Internet应用的开发,Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。

Java语言是健壮的。Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。安全检查机制使得Java更具健壮性。

Java语言是安全的。Java提供了一个安全机制以防恶意代码的攻击。Java对通过网络下载的类具有一个安全防范机制,并提供安全管理机制让Java应用设置安全哨兵。

Java语言是体系结构中立的。Java程序(后缀为java的文件)在Java平台上被编译为体系结构中立的字节码格式(后缀为class的文件),然后可以在实现这个Java平台的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。

Java语言是跨平台的。Java程序的字节码文件可以在任何一个操作系统上运行。

2.编译Java Application程序的命令是什么?运行命令是什么?

编译命令:javac 源程序的文件名

运行命令:java main方法所在类的类名

3.Java应用程序分几类?各有什么特点?

不同的Java程序运行在不同的环境中,习惯上将运行环境相同的Java程序归为一类,可以分3类:

Java Application应用程序,属于JavaSE

Applet小程序(目前实际开发中基本不使用)

Servlet程序(在JavaEE中使用)

二、编程题

编写一个文件名为FirstProgram的Java Application,功能是输出“Hello,EveryOne!”,写出编译和运行文件的命令和编译器产生的文件名。

程序源码:

public class FirstProgram{

public static void main(String args[]){

n(“Hello,EveryOne!”);

}

}

编译命令:

javac

运行命令:

java FirstProgram

第2章

1.编程实现键盘输入一个人的出生年份,计算出他这辈子能过几个闰年。(以100岁为寿命长度。)

package chapter2;

import r;

/*

*编程实现键盘输入一个人的出生年份,计算出他这辈子能过几个闰年。(以100岁为寿命长度。)

*/

public class GetYear {

public static void main(String args[]) {

n("请输入出生年份");

Scanner reader = new Scanner();

int firstYear = t();

int length = 100;

int year;

for (int i = 0; i <= length; i++) {//包含第100年

year = firstYear + i;

if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)

n(year);

}

}

}

2.用while循环求Fibonacci序列。

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89……

package 2;

/**

* 斐波那契数列(Fibonacci sequence),又称黄金分割数列.

* 因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,

* 故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,

* 斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)

* @author Administrator

*

*/

class GetFibonacci {

//getFib(int n)用于计算斐波那契数列中第n项的值

static int getFib(int n) {

if(n==0||n==1)

return 1;

return getFib(n-2)+getFib(n-1);

}

public static void main(String args[]) {

int max=20;//求0-max项范围内的斐波那契数列

int i=0;

while(i<20){

(getFib(i)+" ");

i++;

if(i%5==0)

n("");//每5个数以后换行

}

}

}

3.用辗转相除法求两个整数的最大公因数。

package chapter2;

/**

* 辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方法。

* 它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,

* 再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。

* 如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。

* @author Administrator

*

*/

public class GreaterCommonFactor {

//求a、b的最大公约数的方法

static void getGreaterCommonFactor(int a,int b) {

int k = 0;

("gcd(" + a + "," + b + ")=");

do {

k = a % b;//如果a

a = b;//让a等于除数

b = k;

} while (k != 0);//当余数k=0时的除数a就是最大公约数

n(a);

}

public static void main(String args[]) {

getGreaterCommonFactor(12,18);

}

}

4.统计一个字符数组中每个字母出现的次数。

package 2;

public class CounteLettersInArray2 {

public static void main(String[] args) {

//letters[]是被统计数组

char[] letters={'a','b','a','c','c','m','s','a','t','b','c'};

//count[]保存26个字母出现的次数,count[0]保存a的次数,count[25]保存z的次数

int[] count=new int[26];

for(int i=0;i<;i++){

count[letters[i]-'a']++; //letters[i]-'a'如果是0,表示a,如果是1表示b

}

for(int i=0;i<;i++){

if(count[i]>0)

n((char)(i+'a')+":"+count[i]);

}

}

}

5.找到数组中所有的数组元素大于平均值的那些元素。

package chapter2;

import r;

public class AnalyzeNumber {

/**

* 数组中所有的数组元素大于平均值的那些元素

*/

public static void main(String[] args) {

Scanner input = new Scanner();

n("请输入要存储的个数");

int n = t();

double[] numbers = new double[n];

double sum = 0;//保存数组的元素之和

n("请输入您想存储的数字");

for (int i = 0; i < ; i++) {

numbers[i] = uble();

sum += numbers[i];

}

double avg = sum / n;

n("平均值为:" + avg);

n("大于平均值" + avg+"的元素有:");

for (int i = 0; i < n; i++) {

if (numbers[i] > avg) {

n(numbers[i]);

}

}

}

}

6.随机产生20个[77,459)的正整数存放到数组中,求数组中的最大值、最小值、平均值及各个元素之和。

package chapter2;

/*

*随机产生20个[77,459)的正整数存放到数组中,求数组中的最大值、最小值、平均值及各个元素之和。

*/

public class ArrayDemo {

static void getArray() {

// 声明一个长度为20的数组

int[] array = new int[20];

// 遍历数组

for (int i = 0; i < ; i++) {

}

//()会产生[0,1)区间中的双精度浮点随机数

int num = (int) (() * (459 - 77) + 77);//产生[77,459)之间的整数

array[i] = num;

(array[i]+" ");

// 声明最大值,最小值,和,平均值

int max = 0;

int min = array[0];

int sum = 0;

int average = 0;

for (int i = 0; i < ; i++) {

// 最大值

if (max < array[i]) {

max = array[i];

}

// 最小值

if (min > array[i]) {

min = array[i];

}

// 和值

sum = sum + array[i];

}

// 平均值

average = sum / ;

// 打印

n("n最大值是" + max);

n("最小值是" + min);

}

n("和是" + sum);

n("平均值是" + average);

}

public static void main(String args[]) {

getArray();

}

第3章

一、问答题

1.面向对象的四个基本特征是什么?如何理解他们?

答:面向对象程序设计包括四个基本特征:抽象、封装、继承和多态。

抽象是根据业务需要,把客观世界的事物中与业务相关的特征和功能归纳总结出来、忽略与本业务无关的特征和功能,从形成类的过程。

封装是指把同一类事物的特征和功能都定义到一个类里,变成类的属性和方法。同时通过访问控制符来定义每个属性和方法的可见性。

继承是类之间的一种重用机制。如果A类继承了B类,则A类拥有了B类的除了私有属性和私有方法外的所有属性和方法,同时可以添加自己特有的属性和方法。

多态是实现接口的多个类或一个父类的多个子类有相同的方法名,但是具有不同的表现方式。例如动物类具有喊叫的方法,但是它的子类猫和子类狗的喊叫效果却不一样。

2.java源程序的结构是什么?

答:源程序结构如下:

package 包名;

import 包名.类名;

import 包名.类名;

[public ] class 类名{

属性变量定义… …

方法定义… … }

… …

[public ] class 类名{属性变量定义… …

方法定义… … }

程序结构说明如下:

(1)package语句放在第一行,且只能有一个package语句;

(2)如果类中使用到了其他包中的类,可以写import语句。import语句必须放在package语句之后、类的定义之前。如果引入多个包中的类,可以写多行import语句。可以用“包名.*”表示引入该包名里的所有类,但不包括子包下的类;

(3)类的定义要放在import语句的后面。一个java源文件可以包括多个类的定义,但是只有一个类可以定义成public。如果另一个类也需要定义成public则必须单独再建

一个java源程序文件。

3.成员变量应该放在什么位置定义?方法内定义的变量是成员变量吗?

成员变量应该放在类的里面并且在方法的外面。方法内定义的变量不是成员变量,只是局部变量。

4.如何创建对象?this代表什么?

对象的创建也称为对象的实例化,是在内存开辟一个区域,保存新创建的对象,一般格式为: 对象名=new 构造方法(参数列表);

new关键字表示创建对象的意思,构造方法是类中定义的构造方法,参数列表是可选的,根据实际的构造方法的参数来写。

this代表当前对象,也就是当前方法所在的对象。一个类可以创建多个对象,而且实例方法肯定是属于一个对象的,但是在类体内还不知道将来创建的对象是什么,所以就用this来代表该方法所在的对象。

5.包的作用是什么?带包类如何执行?环境变量classpath如何配置?

通过包的定义可以起到两个作用:一是解决命名冲突问题,在同一个包中的类不能重名,但在不同包中的类可以重名;二是通过包以及访问权限控制符可以限制不同包之间类的访问权限。

运行时要用java 报名.类名。

Classpath也该设置为该包所在的文件夹,而不是类文件本身所在的文件夹。

二、编程题

编写一个三角形类,要求能够计算三角形的面积和周长。从键盘输入一个三角形的3条边的长度,并用这三条边创建一个三角形对象,输出此三角形对象的面积和周长。

package 3;

import r;

public class Triangle {

public void setB(double b) {

public double getB() {

}

return b;

public void setA(double a) {

}

this.a = a;

private double a,b,c;

public double getA() {

}

return a;

}

}

this.b = b;

public double getC() {

}

public void setC(double c) {

}

public Triangle(double a, double b, double c) {

}

public double getArea(){

}

public double getPerimeter(){

}

public static void main(String[] args) {

}

Scanner sc=new Scanner();

double a=uble();

double b=uble();

double c=uble();

if(!(a+b>c&&a+c>b&&b+c>a)){

}

Triangle triangle=new Triangle(a,b,c);

n("面积:"+a());

n("周长:"+imeter());

n("您输入的3个边长不能构成一个三角形");

return;

return a+b+c;

double p=(a+b+c)/2;

return (p*(p-a)*(p-b)*(p-c));

super();

this.a = a;

this.b = b;

this.c = c;

this.c = c;

return c;

第4章

有哪几种用法?super有哪几种用法?

this主要有三种用法。

(1)用this来引用当前对象的成员变量或成员方法。

(2)用this来调用类中的另一个构造方法。

(3)把this当做参数传递给其他方法

super主要有两种用法。

(1)引用父类的成员变量或成员方法。

(2) 调用父类的构造方法。

2.变量的隐藏和方法的覆盖有什么区别?

当父类和子类的属性名字一样时,在子类中默认使用的是子类定义的属性,除非明确使用super来调用,所以在子类对象的内存里实际上有2个同名的变量,默认使用的是子类的变量,这种现象称作子类变量隐藏了父类的同名变量。

当父类和子类定义的方法名一样时,子类对象内存里只有子类定义的方法,不再有父类定义的方法,这种现象称作子类的方法覆盖了父类的同名方法。

3.请介绍一下4种访问控制符的作用。

java一共定义了四种访问权限控制符:private、默认权限、protected、public,通过权限控制符和包能够控制访问权限。

(1)private

private可以用来修饰成员变量、成员方法、构造方法以及内部类(内部类是定义在另一个类里面的类,跟成员变量一样属于另一个类的成员)。private修饰的成员只能被它所属的类内的其他方法访问,不能被该类以外的其他类访问。

(2)默认访问权限

默认访问权限也称为包访问权限,不写访问控制符的就是默认访问权限。默认访问权限可以用来修饰成员变量、成员方法、构造方法、类和接口。默认访问权限定义的内容可以被同一个包中的类所访问,包括它本身,但不能被别的包中的类不能访问。

(3)protected

protected可以用来修饰成员变量、成员方法、构造方法以及内部类。protected修饰的成员可以被同一个包内的其他类访问,不同包如果是它的子类的话也可以访问,其他包中不是它的子类的不能访问。

(4)public

public可以用来修饰成员变量、成员方法、构造方法以及类和接口。public修饰的成员可以被任何类访问,无论是否在同一个包内。

类和类成员都存在访问级别的定义。对于普通外部类来说,只有public和默认权限两种,普通外部类不能使用protected和private修饰符。

类的成员(包括内部类)的访问级别有四种:private、默认方式、protected、public。

4.类变量和实例变量有什么区别?

类的成员变量有2种:一种是类变量,一种是实例变量。定义成员变量时,若变量前有关键字static,则称为类变量,若没有static关键字,则称为实例变量。类变量存贮在类的公用区,属于类所有,所有该类的对象共享这一个类变量,而实例变量属于对象所有,每个对象拥有自已独立的实例变量,保存在对象的内存中。

5.类方法如何调用,是否必须创建对象才能调用类方法?

方法声明时,方法名前不加static的是实例方法,加static的是类方法。

类方法调用时不必创建对象就可以调用。

调用类方法有两种格式:

对象名.方法() 或者 类名.方法()

建议使用: 类名.方法();

6.实例方法如何调用?

对象名.方法();

修饰类、变量、方法时有什么含义?

final修饰的类表示在该类不能有子类。

final修饰变量有3种情况:

final修饰的类变量只能被赋值一次,以后不能改变。要么定义时赋值,要么在类的初始化代码块中赋值,以后不能再赋值。

final修饰的实例变量只能被赋值一次,以后不能改变。要么定义时赋值,要么在构造方法中赋值,以后不能再赋值。

final修饰的局部变量只能被赋值一次,以后不能改变。要么定义时赋值,要么在后续代码中赋值一次,以后不能再赋值。

final修饰的成员方法表示在子类中不能被覆盖。

第5章

1.接口与抽象类有什么区别?什么情况下使用接口?什么情况下使用抽象类?

抽象类与接口紧密相关。然而接口又比抽象类更抽象,这主要体现在他们的差别上:

(1)类可以实现多个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口。接口可以支持多继承;

(2)抽象类中可以有普通方法,接口里的方法都是抽象方法,且都是public方法;

(3)抽象类中的成员变量可以被不同的修饰符来修饰,可以有实例变量,也可以有类变量,接口中的成员变量默认的都是public、static、final的变量;

(4)抽象类中有构造方法,接口中不能有构造方法,所以也不能创建对象。

抽象类是对象的抽象,里面的抽象方法也是对子类的一种规范,也可以有普通方法,这些普通方法子类可以继承使用,而接口只是一种行为规范。

那么什么情况该用抽象类,什么情况该用接口呢?主要是看现实的应用场景。如果把现实问题抽象出来后更符合类的特征,具有实例变量、非抽象的方法,那么只能是用抽象类;如果实际问题只能抽象出需要规范的功能方法,而且这些方法不知道如何实现,需要在子类再实

现,不能抽象出实例变量,那么就应该使用接口。当然这时使用抽象类也可以,但是会丧失灵活性,因为其他类继承该抽象类后就不能再继承别的类了。

2.什么是多态?多态的好处是什么?多态有哪几种实现方式?

通俗的说,多态是指实现接口的多个类或一个父类的多个子类虽然有相同的方法,但是具有不同的表现方式。

Java中多态有两种实现形式。一种是通过方法的重载,一种是通过方法覆盖,即子类通过覆盖父类的方法或类实现接口的方法。

方法的重载是指一个类中定义了多个名字相同、参数不同的方法。当实际调用时,java编译器会根据参数的不同来自动决定调用哪个方法。

利用子类覆盖父类的方法或者利用实现接口的方法来实现的多态,是在程序运行期才能决定应该运行的哪个子类对象的方法,因而称为动态多态。

3.内部类有几种形式?

内部类有4种形式:实例成员内部类、静态内部类、局部内部类、匿名内部类。

4.外部类里面如何使用实例成员内部类?其他类里如何使用实例成员内部类?

在外部类里使用内部类跟使用普通类一样,直接调用即可。

但是在其他类里使用内部类有与使用普通类语法不一样,有单独的语法格式,需要分为两步,具体如下:

外部类 外部类对象名 = new 外部类构造方法(实参列表);

外部类.内部类 内部类对象名= 外部类对象名.new 内部类构造方法(实参列表);

5.在外部类里面如何使用static内部类?在其他类里如何使用static内部类?

在外部类中使用静态内部类跟使用普通类一样,直接调用即可。

在其他类中使用静态内部类,不需要创建外部类的对象,就可以创建内部静态类的对象。格式如下:

外部类.内部类 内部类对象名= new 外部类.内部类(实参列表);

6.内部匿名类如何定义类体和创建对象?

创建匿名内部类必须事先有一个接口或者父类,把内部匿名类定义为接口的一个实现类或者是某个父类的子类。实际上是把创建对象和定义匿名内部类的类体同时进行的。格式如下:

new 父类构造器(参数列表){

//匿名内部类的类体部分

}

或者

new 接口(){

//匿名内部类的类体部分

}

第6章

一、问答题

1.什么是异常?异常分哪几种?

在编写程序过程中,会出现各种错误。有语法错误,有程序运行过程中出错,还有的程序运行过程中尽管没有报错,但出来的结果不对,这属于程序的逻辑错误。除了语法错误和逻辑错误外,例如,想打开的文件不存在、网络连接中断、操作数超出预定范围、正在装载的类文件丢失、访问的数据库打不开等等。Java把这些非正常的意外事件称为异常(Exception,又称为“例外”)。

系统定义异常:指java中对一些常见问题提供了对应的异常类。

用户自定义异常:程序员对特定问题,根据java规范编写的异常类。

Java中所有的异常类都是ble的子类。Throwable类有两个直接子类:Error类及Exception类。

Error类描述的是内部系统错误,包括动态链接失败、虚拟机错误等,Java程序不做处理。这类异常主要是和硬件有关系,而不是由程序本身抛出。通常不由Java程序处理,用户也无法捕获。

Exception类是Java程序中需要大量处理的。

Java中定义了许多Exception的子类,这些子类分为两种:RuntimeException和非运行时异常。

运行时异常

运行时异常RuntimeException是一些可以通过适当的处理而避免的异常,在程序运行中可自动由JVM引发并处理,编程时不需捕获或声明。如:被0除,数组下标越界等,这类异常是编码时考虑不周产生的,完全可以通过判断来避免。

非运行时异常

非运行时异常,通常由环境因素引起的,与程序员无关,如输入、输出异常IOException,文件不存在、无效的URL等等。Java编译器要求Java程序必须捕获或声明所有的非运行时异常。

2.Java通过什么语句来捕获异常?

java可以通过try、catch、finally语句来捕获异常。

3.简述Java的异常处理机制

概括的说,java的异常处理机制就是三个步骤:

(1)异常的抛出。程序在执行过程中发生异常,java虚拟机就会发现并产生一个异常对象,这个过程就是异常的抛出。可以由系统来抛出异常,也可以由程序员在代码中使用throw强制抛出某种类型的异常。

(2)异常的捕获。出现异常后,java可以通过try、catch、finally语句来捕获异常,并做相应的处理,这个过程称为异常的捕获。

(3)如果没有捕获异常的代码,程序将终止运行。

4.简述try、catch、finally的使用方法

try-catch-finally基本格式:

try{

//可能产生异常的代码放在此处

}

catch (异常类名1 异常对象名){

//在此处理异常类型1对应的异常

}

catch (异常类名2 异常对象名){

//在此处理异常类型2对应的异常

}

finally{

//最终的程序出口,往往会写一些清理资源的语句放在此处

}

try-catch-finally语句把可能产生异常的语句放入try{ }语句块中。当try代码块中的语句发生了异常,系统将这个异常发生的代码行号、类别等信息封装到一个对象中,并将这个对象传递给catch代码块。程序就会跳转到catch代码块中执行。

在try{ }语句后紧跟一个或多个catch块,用于对try代码块中所生成的异常对象进行处理,每一个catch块处理一种可能抛出的特定类型的异常。在运行时刻,如果try{ }语句块中产生的异常与某个catch块处理的异常类型相匹配(匹配是指异常参数类型与实际产生的异常类型一致或是其父类),则将停止执行try中的剩余语句,并跳转到catch中执行该catch语句块。

finally语句是捕获异常的最后一步,是通过finally语句为异常处理提供一个统一的出口。finally子句是可选的。无论try所指定的程序块中是否抛出异常、抛出哪种异常,finally关键字中包含的代码都要被执行。

二、编程题

练习自定义异常的用法。定义一个年龄异常类AgeException,定义一个Person类,具有name(姓名)、age(年龄)属性,以及setAge(int age)方法,当给age属性的值不在0-200范围内时抛出年龄异常。

public class AgeException extends Exception{

public AgeException(){

//调用父类的构造方法,将"年龄超过范围"赋值给父类的message变量

super("年龄超过范围");//异常错误信息是固定的

}

public AgeException(String message){

//调用父类的构造方法,将message传递给父类的message变量

super(message);//异常错误信息由调用者指定

}

}

public class People {

private String name;//姓名

private int age;//年龄

public String getName() { return name; }

public void setName(String name) { = name; }

public int getAge() { return age; }

public void setAge(int age) throws AgeException{

if(age<0||age>200)

throw new AgeException();

}

= age;

}

public static void main(String[] args) {

People p=new People();

try {

(400);

} catch (AgeException e) {

n("给age赋值错误:"+sage());

}

}

第7章

1.从键盘输入一个由空格和字符组成的字符串,首先用空格作为分隔符把该字符串拆分成多个部分,然后把每个部分的字符倒序排列后输出。

public class WordConverseandSplit {

public static String[] spitConverse(String s) {

String ss[] = (" ");//用空格把s拆分成字符串数组ss

for (int i = 0; i < ; i++) {

StringBuffer sb = new StringBuffer(ss[i]);

e();//利用StringBuffer的reverse方法实现倒序排列

ss[i]=ng();//把反转后的字符串赋值给ss[i]

}

return ss;

}

public static void main(String args[]){

Scanner sc=new Scanner();

String s1=ne();//输入一行字符

String[] s=spitConverse(s1);//调用spitConverse实现拆分、倒序排列

for(int i=0;i<;i++)

n(s[i]);

}

}

2.编写程序,功能如下:获取键盘输入的字符串,输出其中重复的字符、不重复的字符以及消除重复字符后的字符串。

/*

*获取命令行参数中的字符串,输出其中重复的字符、不重复的字符以及消除重复字符后的字符串。

*/

class CharDemo {

public static void main(String[] args) {

}

}

String str = "abcdeafblmbnopawc";

n("原字符串:" + str);

Set set1 = new HashSet();// 消除重复后的字符集合

Set set2 = new HashSet();// 重复的字符集合

Set set3 = new HashSet();// 不重复的字符集合

// 把字符串转为字符数组

char[] cs = Array();

for (char c : cs) {

}

boolean b = (c);//如果true说明c跟前面的字符不重复,成功添加到set1if (!b) {//为false,说明

(c);

}

// 把消除重复后的字符赋给set3

(set1);

// 把消除重复后的字符 - 重复的字符 = 不重复的字符

All(set2);

n("====消除重复后的字符========");

for (char c : set1) {

(c + " ");

}

n("n====重复的字符========");

for (char c : set2) {

(c + " ");

}

n("n====不重复的字符========");

for (char c : set3) {

(c + " ");

}

3.定义一个Employee类:

属性变量:name(String型),age(int型),salary(double型)

把若干Employee对象放在List中,排序并遍历输出,排序规则:按salary降序排序,salary相同时按age降序排序,age也相同时按照name升序排列。把若干Employee对象放在Set中并遍历,要求没有重复元素。

/*

*定义一个Employee类:

*属性变量:name(数据类型:String),age(数据类型:int),salary(数据类型:double)

*把若干Employee对象放在List中,排序并遍历输出,排序规则:按salary降序排序,salary相同时按age降序排序,age也相同时按照name升序排列。把*若干Employee对象放在Set中并遍历,要求没有重复元素。

*/

public class Employee {

private String name;

private int age;

private double salary;

public String getName() {

return name;

}

public void setName(String name) {

= name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

= age;

}

public double getSalary() {

return salary;

}

public void setSalary(double salary) {

= salary;

}

public Employee() {

super();

// TODO Auto-generated constructor stub

}

public Employee(String name, int age, double salary) {

super();

= name;

= age;

= salary;

}

@Override

public String toString() {

return "姓名:" + name + ", 年龄:" + age + ", 工资:" + salary ;

}

}

class EmployeeList{

public static void main(String[] args) {

Employee e1 = new Employee("Alis",20,3000);

Employee e2 = new Employee("Tom",22,3000);

Employee e3 = new Employee("Jack",22,3000);

Employee e4 = new Employee("Lily",21,3500);

Employee e5 = new Employee("Mike",20,2900);

Employee e6 = new Employee("Bobo",23,4000);

List list = new ArrayList();

(e1);

(e2);

(e3);

(e4);

(e5);

(e6);

//遍历

for (Employee e : list) {

n(e);

}

n("=============排序后================");

for (int i = 1; i < (); i++) {

for (int j = 0; j < () - i; j++) {

Employee emp1 = (j);

Employee emp2 = (j+1);

//比较收入

if(ary() < ary()){

(j, emp2);

(j+1, emp1);

}else if(ary() == ary()){

//比较年龄

if(() < ()){

(j, emp2);

(j+1, emp1);

}else if(() == ()){

if(e().compareTo(e()) > 0 ){

(j, emp2);

(j+1, emp1);

}

}

}

}

}

//遍历

for (Employee e : list) {

n(e);

}

}

}

package 7;

import p;

import or;

import ;

import ;

/*

*将某公司职员信息放入HashMap中,name:姓名(提示:使用HashMap),最后将职工信息打印出来。

*/

public class EmployHashMap {

public static void main(String[] args) {

// TODO Auto-generated method stub

}

Employee e1 = new Employee("张天",20,3000);

Employee e2 = new Employee("王龙",22,3000);

Employee e3 = new Employee("马浩哲",22,3000);

Employee e4 = new Employee("孙峰",21,3500);

Employee e5 = new Employee("苏素",20,2900);

Map mp=new HashMap();

("张天", e1);

("王龙", e2);

("马浩哲", e3);

("孙峰", e4);

("苏素", e5);

Set set=();

Iterator it=or();

while(t()){

Employee em=(Employee)(());

(e());

n();

}

}

第8章

1.编写Java Application,完成以下功能。

D盘下创建一个文件为文件,判断是文件还是目录,再创建一个目录IODemo,之后将移动到IODemo目录下去;之后遍历IODemo这个目录下的文件。

package 8;

import ;

import ption;

public class Excercise_08_01 {

/**

* 1. 在电脑D盘下创建一个文件为文件, 判断他是文件还是目录,再创建一个目录IODemo,

* 之后将移动到IODemo目录下去; 之后遍历IODemo这个目录下的文件

* 程序分析: 1、文件创建使用File的createNewFile()方法

* 2、判断是文件用isFile(),判断是目录用isDirectory

* 3、创建目录用:mkdirs()方法 4、移动文件用:renameTo

* 5、遍历目录用:list()方法获得存放文件的数组,foreach遍历的方法把文件打印出来

*/

public static void main(String[] args) {

// 在电脑D盘下创建一个文件为文件

File file = new File("D:", "");

// 创建文件,返回一个布尔值

boolean isCreate;

try {

isCreate = NewFile();

if (isCreate) {

n("创建文件成功!");

} else {

n("创建文件失败!文件可能已经存在");

}

} catch (IOException e) {

n("创建文件失败!");

}

// 判断是文件还是目录,

if (()) {

n("是一个文件");

} else {

}

n("是一个目录");

// 再创建一个目录IODemo

File fileDiretory = new File("D:/IODemo");

if(()){

n("创建文件夹D:/IODemo成功");

}else{

n("创建文件夹D:/IODemo失败,文件夹可能已经存在");

}

File file2=new File(fileDiretory,"");

// 移动到IODemo目录下去

if (To(file2)) {

n("文件移动成功!");

} else {

}

}

n("文件移动失败,目标文件可能已经存在");

}

// 遍历IODemo目录下的文件

String[] arr = ();

for (String string : arr) {

n(string);

}

2.已知文件里的内容为“EEbcdea22dferwpliCC123yh”,编写程序读取该文件内容,要求去掉重复字母(区分大小写)并按照自然排序顺序后输出到文件中。即文件内容应该为“ebcda2fr……”这样的顺序输出。

package 8;

import ;

import putStream;

import tputStream;

import ption;

import t;

/*

在E盘中构造一个文本,向文本中写入内容;AaaAcDFAFAOFJIO132

向E盘写入数据,创建输出流

读取该文件内容,去除重复的字母(区分大小写)并且按照自然排序输出到文件

想要输出数据(写入数据),需要创建输入流对象

因为文本要排序,且不重复,可以将数据存入HashSet中

再通过遍历集合将数据按字节的方式写入到b中

即文件内容为:123ABCabc这种格式

*/

public class Excercise_08_02 {

public static void main(String[] args) throws IOException {

// [1]创建hashSet集合

TreeSet charTree = new TreeSet<>();

// [1]在目标目录中创建和

File fileA = new File("E:" + tor + "");

File fileB = new File("E:" + tor + "");

NewFile();

NewFile();

// 创建输出流,向文本中写入数据

FileOutputStream outputA = new FileOutputStream(fileA);

String strA = "ADFFBOG123cgfser";

// 写入数据

(es());

}

}

// 刷新流

();

// 关闭流

();

// 读取中的内容,并将其里面的文本内容赋值给hashSet集合

// 创建输入流,读取中数据

FileInputStream inputA = new FileInputStream(fileA);

byte[] b = new byte[ble()];

int len = 0;

/*

* TreeSet charStr = new TreeSet<>(); int fileChar = 0;

* while((fileChar=())!=-1){ (fileChar); }

*/

while ((len = (b)) != -1) {

}

// 得到A中的内容,并生成字符串格式

String strFromA = new String(b);

// 将字符串强转为字符型数组

char[] charA = Array();

// 将字符数组遍历并赋值给hashSet集合

for (char c : charA) {

(c);

}

// 读取结束,关闭输入流

();

// 将hashset集合中的数据写入到中

/* n(charTree); */

/* n(ng()); */

// 创建输出流,写入数据

FileOutputStream outputB = new FileOutputStream(fileB);

// 将charTree中的字符集转换为String型

for (char ch : charTree) {

(f(ch).getBytes());

}

// 刷新输出流

();

// 关闭流

();

3.编写Java Application,完成以下功能。

用户User类以下成员变量和成员方法。

成员变量有:用户名uname(String)、账号uid(String)、密码pwd:(String);

构造方法有:有参构造方法,无参构造方法;

成员方法有:成员变量对应的get,set方法,以及toString方法。

创建一个User对象,并将该对象写入F:。

从F:中读取该对象数据,在控制台显示。

package 8;

import ;

import putStream;

import tputStream;

import ption;

import InputStream;

import OutputStream;

import izable;

class User implements Serializable {// 必须实现Serializable接口

String uid;

String pwd;

String uname;

public User(String _uname, String _uid, String _pwd) {

= _uname;

= _uid;

= _pwd;

}

public String getUname() {

return uname;

}

public void setUname(String name) {

= name;

}

public String getUid() {

return uid;

}

public void setUid(String id) {

= id;

}

}

public String getPwd() {

return pwd;

}

public void setPwd(String pwd) {

= pwd;

}

public String toString() {

}

return "姓名:" + + "账号:" + + " 密码:" + ;

// 将对象写入磁盘文件

public class ObjectEmployDemo {

public static void main(String[] args) throws IOException, ClassNotFoundException {

}

// 将对象信息写入到文件中,事先已经在硬盘中建立一个文件

File f = new File("F:");

writeObjec(f);

n("Write OK");

readObject(f);

n("Read OK");

// 定义方法把对象的信息写到硬盘上------>对象的序列化。

public static void writeObjec(File f) throws IOException {

FileOutputStream outputStream = new FileOutputStream(f);// 创建文件字节输出流ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

对象

bject(new User("马晓明", "sdjzu", "123"));

// 最后记得关闭资源,()内部已经将outputStream对象资源释放了,所以只需要关闭objectOutputStream即可

();

}

}

// 把文件中的对象信息读取出来-------->对象的反序列化

public static void readObject(File f) throws IOException, ClassNotFoundException {

// 创建文件字节输出流对象

FileInputStream inputStream = new FileInputStream(f);

ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);

User user = (User) ject();

n(user);

}

4.使用随机文件流类RandomAccessFile将一个文本文件倒置读出。

package 8;

import ;

import AccessFile;

public class RandomAccessDemo {

/**

* 使用随机文件流类RandomAccessFile将一个文本文件倒置读出。 程序分析:

* RandomAccessFile的seek方法能把读取文件的光标移动到具体的位置 但是还是有地点值得注意的是一个字母或数字是占用一个字节的,

* 一个汉字是占用两个字节。

*/

public static void main(String[] args) {

}

}

// 要读取的文件的地址

File file = new File("D:/java/");

try {

RandomAccessFile raf = new RandomAccessFile(file, "r");

long length = ();

StringBuffer sb = new StringBuffer();

while (length > 0) {

length--;

(length);

int c = (char) te();

// 如果asc码<=255,>=0,则判断是个英文字符,添加到字符串中.

if (c >= 0 && c <= 255) {

((char) c);

} else {

// 如果不在asc码范围内,则判断是个汉字字符

// 汉字字符是占2个字节的,所以length再退一个字节

length--;

(length);

byte[] cc = new byte[2];

// cc被复制为文件中连续的两个字节

lly(cc);

(new String(cc));

}

}

n(sb);

();

} catch (Exception e) {

tackTrace();

}

第9章

一、问答题

1.简述泛型的作用。

Java引入泛型后有2个优点:

一是省去了强制类型转换,二是能够在编译期发现类型错误,三是可以支持多个数据类型,程序更通用。

2.简要介绍什么是类型擦除。

JDK1.5引入的泛型实际上是一种编译器层次上技术,在虚拟机层次上并不直接支持泛型。为了使java代码与以前版本兼容,编译器使用一种擦除技术,编译器在编译时会自动“去除”有关泛型的定义,而加入了强制类型转换。所有对类型变量的引用被替换成类型变量的上限,通常是Object。

三、编程题

1.编写一个泛型类,要求能够计算一个数值型数组的平均值。输入一个Integer类型数组和一个Double型数组,测试你编写的泛型类。

public class Class1 {

T[] t;

public Class1(T[] t) {

super();

this.t = t;

}

public T[] getT() {

return t;

}

public void setT(T[] t) {

this.t = t;

}

public double average (){

double s=0;

for(int i=0;i<;i++)

s=s+t[i].doubleValue();

return s/;

}

public static void main(String[] args) {

Integer[] i={1,2,3,4};

Class1 class1=new Class1(i);

n(class1. average ());

Double[] d={1.2,3.5,4.5,12.2};

Class1 class2=new Class1(d);

n(class2. average ());

}

}

2.编写一个static泛型方法,要求能够计算一个数值型数组的平均值。输入一个Integer类型数组合一个Double型数组,测试你编写的泛型方法。

public class Class2 {

public static double average(T[] t){

double s=0;

for(int i=0;i<;i++)

s=s+t[i].doubleValue();

return s/;

}

public static void main(String[] args) {

Integer[] i={1,2,3,4};

n(e(i));

Double[] d={1.2,3.5,4.5,12.2};

n(e(d));

}

}

第10章

一、问答题

1.java有哪些常用的布局?每种布局的特点是什么?

主要有FlowLayout、BorderLayout、GridLayout、CardLayout 、BoxLayout等布局管理器类以及空布局。

FlowLayout布局也称为流式布局,他是JPanel的默认布局方式。他是按照组件添加的先后顺序,默认从左到右依次将组件添加到容器中,根据容器宽度,放满一行后,自动从下一行开始由左到右排列组件。

BorderLayout是一个边框布局,他是Window类型的容器的默认布局,例如JFrame、JDialog的默认布局都是BorderLayout。他可以对容器组件进行安排,并调整其大小,使其符合下列五个区域:北区、南区、东区、西区、中区。每个区域只能包含一个组件,并通过相应的常量进行标识:NORTH、SOUTH、EAST、WEST、CENTER。

GridLayout是一个网格布局,按照多行多列的方式排列组件,每个行列的交叉区域称为一个单元格,每个组件占据一个单元格,并根据单元格的大小调整其大小。

CardLayout 称为卡片布局。它将容器中的多个组件像扑克牌一样层叠在一起,每个组件被当做一张卡片。第一个加到容器的组件在最上面,第二个加入的组件在第一张的下面,依次顺序排列,最后加入的组件在最下面。同一时刻只能显示一个组件。

空布局有时也叫自由布局。空布局其实就是不指定布局,通过指定各个组件的坐标来指定组件的绝对位置。

2.FoucusListener中声明了哪几种方法?什么情况下执行哪个方法?

FocusListener接口中只声明了2个方法:

void focusGained(FocusEvent e):事件源组件获得键盘焦点时调用。

void focusLost(FocusEvent e):事件源组件失去键盘焦点时调用。

3.MouseListener中声明了哪几种方法?什么情况下执行哪个方法?

在事件源上发送以下5种动作时需要使用MouseListener接口来处理:按下鼠标键、释放鼠标键、单击鼠标、鼠标进入、鼠标离开。接口中声明的5个方法是:

public void mouseClicked(MouseEvent e):鼠标在组件上单击时

public void mousePressed(MouseEvent e):鼠标组件上按下时

public void mouseReleased(MouseEvent e):鼠标组件上释放时

public void mouseEntered(MouseEvent e):鼠标进入组件时

public void mouseExited(MouseEvent e):鼠标离开组件时

4.实现监听器有哪3种方法?

监听器的编写有三种方法:

(1)编写一个单独的类实现某个监听器接口或继承某个监听器适配器类。

(2)让窗口类直接实现相应的接口。

(3)用匿名类的方式直接继承某个监听器适配器类或实现某个监听器接口(最常用的方法)。

二、选择题

1.获取JTextField组件中输入的文本值的方法是:(A)

A. getText() t() C. getLabel() D setLabel()

2.获取一个复选框是否选中的方法是:(A)

A. isSelected() B. isChecked() C. setChecked() D. setSelected()

3.给一个按钮注册动作监听器的方法是:(B)

A. addActionEvent() B. addActionListener()

C. addMouseListener() D. addItemListener()

三、编程题

1.设计一个用户注册的界面,包括用户名、密码输入框,性别单选按钮,表示爱好的篮球、足球、乒乓球复选框,表示学历的下拉列表框,注册按钮和取消按钮。

public class Register extends JFrame {

//定义要在窗口中显示的属性,即组件

JLabel lblUserName=new JLabel(" 用户名:");

JTextField txtUserName=new JTextField(10);

JLabel lblPassword=new JLabel(" 密码:");

JPasswordField txtPassword=new JPasswordField(10);

JLabel lblSex =new JLabel(" 性别:");

ButtonGroup group=new ButtonGroup();

JRadioButton rbtMale=new JRadioButton("男",true);

JRadioButton rbtFeMale=new JRadioButton("女",false);

JLabel lblHobby =new JLabel(" 爱好:");

JCheckBox cbxBasketball=new JCheckBox("篮球",true);

JCheckBox cbxFootball=new JCheckBox("足球");

JCheckBox cbxTableTennis=new JCheckBox("乒乓球");

JLabel lblXueLi =new JLabel(" 学历:");

JComboBox jbxXueLi=new JComboBox();

JButton btnOk=new JButton("确定");

JButton btnCancel=new JButton("取消");

JPanel p=new JPanel();JPanel pJbxx=new JPanel();

public Register(){

//将组件放入窗口中,基本信息放在上边的面板pJbxx中,简历放在下边的面板pJianLi中

out(new GridLayout(0,4));//每行放4个组件

//学号和密码占一行

(lblUserName);(txtUserName);

(lblPassword);(txtPassword);

oChar('A');t("abcd");

//性别占一行,不够4个,用一个用空的JLabel填充

(lblSex);(rbtMale);(rbtFeMale);

(new JLabel());

//把男女单选按钮放到一个组里,实现互斥

(rbtMale);(rbtFeMale);

//学院占一行,该行不够4个,用2个空的JLabel填充

(lblXueLi);(jbxXueLi);

(new JLabel());(new JLabel());//

m("博士");//添加下拉选择项

m("硕士");

m("本科");

m("专科");

//爱好占一行

(lblHobby);(cbxBasketball);

(cbxFootball);(cbxTableTennis);

//确定和重置按钮占一行,该行不够4个,用2个空的JLabel填充

(new JLabel());(btnOk);(btnCancel);

(new JLabel());

(pJbxx);

add(p,);

aultCloseOperation(_ON_CLOSE);

}

public static void main(String[] args) {

Register frame=new Register();

e(500,300);

ible(true);

}

}

2.设计一个求三角形面积的图形界面程序,要求通过3个输入框输入3个边长,当单击“计算”按钮时,能够计算以输入的3个边长所形成的三角形的面积。要求能够判断输入的3个边长是否是数字,三个边长是否能够构成合法的三角形。

public class TriangleFrame extends JFrame{

JLabel lblEdge1=new JLabel("边长1");

JLabel lblEdge2=new JLabel("边长1");

JLabel lblEdge3=new JLabel("边长1");

JLabel lblArea=new JLabel("面积");

JTextField txtEdge1=new JTextField(10);

JTextField txtEdge2=new JTextField(10);

JTextField txtEdge3=new JTextField(10);

JTextField txtArea=new JTextField(10);

JButton btnCalculate=new JButton("计算");

JButton btnReset=new JButton("清空");

JPanel p=new JPanel();

public TriangleFrame(){

super("计算机三角形面积");

out(new GridLayout(5,2));

(lblEdge1);(txtEdge1);

(lblEdge2);(txtEdge2);

(lblEdge3);(txtEdge3);

(btnCalculate);(btnReset);

(lblArea);(txtArea);

(p);

aultCloseOperation(_ON_CLOSE);

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

double a=f(t());

double b=f(t());

double c=f(t());

if(!(a+b>c&&a+c>b&&b+c>a)){

ssageDialog(null, "您输入的3个边长不能构成一个三角形","提示信息",_MESSAGE);

return;

}

Triangle triangle=new Triangle(a,b,c);

t(f(a()));

}

});

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

t("");

t("");

t("");

}

});

}

public static void main(String[] args) {

TriangleFrame frame=new TriangleFrame();

e(300,300);

ible(true);

}

}

class Triangle {

private double a,b,c;

public double getA() {

return a;

}

public void setA(double a) {

this.a = a;

}

public double getB() {

return b;

}

public void setB(double b) {

this.b = b;

}

public double getC() {

return c;

}

public void setC(double c) {

this.c = c;

}

public Triangle(double a, double b, double c) {

super();

}

this.a = a;

this.b = b;

this.c = c;

}

public double getArea(){

double p=(a+b+c)/2;

return (p*(p-a)*(p-b)*(p-c));

}

第11章

一、问答题

1.请介绍线程生命周期中的几种状态,并说明他们之间的转化规则。

线程的生命周期从大的方面分有五个状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。

程序使用new新建一个线程对象后,线程对象就存在了,JVM会为其分配内存,初始化成员变量等,这时线程处于新建状态。

当线程对象调用start()方法后,线程将进入就绪状态。此时线程依然没有运行,而是等待获取CPU执行,所以就绪状态也称为可执行状态。

处于就绪状态的线程如果得到了CPU则开始运行,此时进入运行状态。运行状态的线程如果CPU分配的时间片用完,则重新进入就绪状态。运行态的线程如果执行完毕就进入死亡状态。处于运行状态线程在执行过程中,碰到阻塞情况线程会进入阻塞状态。

当处于阻塞状态的线程在阻塞原因消除后会重新进入就绪状态。

当线程的run()执行完毕,或者调用了stop(),线程就会消亡。

线程创建有哪几种方法?

常用的有2种方法:(1)通过继承Thread类来建立线程类。Thread类的对象就是一个线程。如果要编写自己的代码,可以编写一个子类来继承Thread类,这个子类的对象就是一个线程了。Thread类中有一个run方法,要在线程中运行的代码需要写在子类的run()方法里,然后调用线程对象的start()方法即可启动线程来运行。

(2)通过实现Runnable接口的方法来实现线程。这需要定义一个线程载体类,该类实现了Runnable接口,并编写run方法。然后建立线程载体对象。最后把线程载体对象传递给Thread类的构造方法建立线程对象。

3.线程调用isAlive()方法时哪几种状态下会返回true?

线程对象的isAlive()方法在就绪、运行、阻塞时都会返回true。

4.请介绍wait()、notify()、notifyAll()方法的用法。

wait()、notify()、notifyAll(),这3个方法其实是Object类中定义的方法,并不是Thread类中新定义的,换句话说,就是每个对象里面都有这些方法。

wait():释放当前对象锁,并进入阻塞队列。

notify():唤醒当前对象阻塞队列里的任一线程(并不保证唤醒哪一个)。

notifyAll():唤醒当前对象阻塞队列里的所有线程。

注意,这三个方法要与synchronized一起使用。

因wait()而导致阻塞的线程是放在阻塞队列中的,因竞争锁失败导致的阻塞是放在同步队列中的,notify()/notifyAll()实质上是把阻塞队列中的线程放到同步队列中去。

另外,wait方法应在循环中使用,否则可能会造成等待的线程无法被唤醒,通常格式如下:

synchronized (obj) {//获得obj的锁

while (<条件不满足>)

();//释放锁并进入等待队列

... // 条件满足,执行其他代码

}

5.线程为什么会死锁?如何加锁才能避免死锁?

通过加锁方式可以让多个线程互斥访问,但是如果加锁的策略不当会出现死锁。因为线程各自需要的锁都被对方把持着,都想获得对方持有的锁,又都不释放自己持有的锁,结果谁也没法往下执行,造成了死锁。

如何解决死锁呢?一个简单的办法是各个线程都按照相同的顺序获得锁。

二、编程题

请编写一个显示时间的程序,要求能够显示时、分、秒,格式为“小时:分钟:秒”,每秒钟更新一次时间。

public class ClockFrame extends JFrame {

JLabel lblClock=new JLabel("");

JButton btnStart=new JButton("开始");

JButton btnStop=new JButton("停止");

MyThread myThread=null;

public ClockFrame(){

super("时钟");

out(new FlowLayout());

(lblClock);(btnStart);(btnStop);

aultCloseOperation(_ON_CLOSE);

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

myThread=new MyThread();

=true;

();

}

});

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

=false;

}

});

}

public static void main(String[] args) {

}

ClockFrame frame=new ClockFrame();

e(300,300);

ible(true);

}

class MyThread extends Thread{

boolean flag=true;

public void run(){

while(flag){

Calendar calendar=tance();

int hour=();

int minute=();

int second=();

t(hour+":"+minute+":"+second);

try{sleep(1000);}

catch(Exception e){}

}

}

}

第12章

一、问答题

1.URL类的作用是什么?如何通过URL类来读取某个网络资源的内容?

在java中提供了一个URL类来封装一个网址对象,URL类在包下,代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录。通过使用Java的URL类就可以对URL资源进行完成读取数据的操作。

通过URL的对象我们可获取网址的信息,例如网址使用的协议、端口号、网址所在主机名、网页路径、文件名等信息,并且可以通过输入流来读取网页内容。

调用URL对象的openStream()方法返回一个输入流对象即InputStream的对象,比如命名为in,通过输入流in对象即可读入输入流的内容。

2.URL和URLConnection的区别是什么?

URL表示一个网址,而抽象类 URLConnection代表应用程序和 URL 之间的通信链接,他也在包下,他的实例可用于读取和写入此 URL 引用的资源。一般通过一个URL对象的openConnection方法来获得URLConnection对象。

3.利用ServerSocket和Socket类编写基于TCP协议的网络通信程序的步骤是什么?通信双方是否必须使用一样的端口号?

客户端程序利用Socket对象与服务器通信一般要经过四步:

(1)连接服务器

连接服务器可以通过在Socket的构造方法中指定服务器的地址(或主机名)和端口号来创

建Socket对象时完成对服务器的连接。

例如:Socket socket= new Socket("localhost",5000);// localhost表示连接本机,连接到本机的5000端口

或者Socket socket= new Socket("127.0.0.1",5000);// 127.0.0.1表示连接本机,连接到本机的5000端口

(2)得到客户端socket对象的输入和输出流

InputStream in= socket. getInputStream ();

一般情况下我们会使用过滤流来包装得到的输入流

DataInputStream din= new DataInputStream(in);

OutputStream out= putStream();

DataOutputStream dout=new DataOutputStreamout);

(3)通过输入输出流读入或发送数据

String s=F();

String sout="你好";

TF(sout);

(4)关闭连接

();();();

服务器端则是用ServerSocket,利用ServerSocket的accept()方法,

accept方法的作用是监听并接受到此套接字的连接。此方法在连接传入之前一直阻塞,直到有客户端的socket对象连接到自己,才继续往下执行。accept方法返回一个本地的socket对象,该socket对象封装了对方的ip地址、端口号和自己的ip地址和端口号。后续客户机和服务器之间的数据通信实际上是通过客户端socket对象和服务器端新生成的socket对象之间进行的。服务器端的ServerSocket对象的作用只是负责监听客户端的连接,然后通过accept方法生成服务器端的socket对象,即两端都各有一个socket对象,都有自己的输入输出流。

客户端和服务端的端口号可以不一样。

4.利用DatagramSocket和DatagramPacket编写基于UDP协议的通信程序的步骤是什么?

(1)发送方创建DatagramSocket对象,比如是ds,ds中封装了自己的端口号。

(2)发送方创建DatagramPacket 的对象,比如是dpSend,dpSend中包含了要发送的数据和对方的地址和端口号。

(3)发送方利用ds的send(dpSend)方法将dpSend发送出去。

(4)接收方创建DatagramSocket的对象,比如是ds,ds的端口号要跟发送方的dpSend的端口号一样。

(5)接收方创建一个空的DatagramPacket 对象,比如是dpReceive。

(6)接收方调用e(dpReceive)方法接收数据包,dpReceive中包含了发送方发送过来的数据。

二、编程题

1.使用ServerSocket和Socket类编写一个两人聊天的程序。

public class ServerFrame extends JFrame {

JLabel lblInput=new JLabel("请输入:");

JTextField txtInput=new JTextField(20); //用于接收用户输入的要发送给对方的字符串

JButton btnSend=new JButton("发送");//点击这个按钮,将txtInput中输入的内容发送出去

JTextArea jtaContent=new JTextArea(10,20); //用于显示自己和对方输入的内容

Socket s;

ServerSocket ss;

Container c=tentPane();

JPanel pUp=new JPanel();

DataOutputStream out;

private void init(){

out(new FlowLayout());

(lblInput);(txtInput);(btnSend);

(pUp,);

(jtaContent,);

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent ae){

String temp=t();

t("");

t(t()+"n我说:"+temp);

try {

TF(temp);

if(("bye")){

();

();

}

} catch (IOException e) {

tackTrace();

}

}

});

try {

ss=new ServerSocket(5000);

s=();//得到自己的Socket对象

out=new DataOutputStream(putStream());//得到输出流,用于发送数据给对方

} catch (UnknownHostException e) {

tackTrace();

} catch (IOException e) {

tackTrace();

}

aultCloseOperation(EXIT_ON_CLOSE);

e(400,300);

ible(true);

}

public ServerFrame(){

super("服务端");

init();

ReceiveThread rt=new ReceiveThread(s,jtaContent); //把本窗口中的Socket对象s和文本区对象jtaContent传递给接收数据的子线程,这样子线程和主程序使用的是同一套对象

();

}

public static void main(String[] args) {

ServerFrame cf=new ServerFrame();

}

}

public class ReceiveThread extends Thread {

Socket s;//将来用聊天主程序中的Socket对象代替,即跟主程序中的是同一个套接字

JTextArea jtaContent;// 将来用聊天主程序中的JTextArea对象代替,即跟主程序中的是同一个文本区,添加到jtaContent中的文字,就会显示在主聊天窗口中的文本区中

DataInputStream in;

public ReceiveThread(Socket s,JTextArea jtaContent){

this.s=s;tent=jtaContent;

}

public void run(){

try {

in=new DataInputStream(utStream());

while(true){

String temp=F();

("n对方说:"+temp);

if(().equals("bye")){

();();

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

}

}

}

public class ClientFrame extends JFrame {

JLabel lblInput=new JLabel("请输入:");

JTextField txtInput=new JTextField(20);//用于接收用户输入的要发送给对方的字符串

JButton btnSend=new JButton("发送");//点击这个按钮,将txtInput中输入的内容发送出去

JTextArea jtaContent=new JTextArea(10,20);//用于显示自己和对方输入的内容

Socket s;

Container c=tentPane();

JPanel pUp=new JPanel();

DataOutputStream out;

private void init(){

out(new FlowLayout());

(lblInput);(txtInput);(btnSend);

(pUp,);

(jtaContent,);

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent ae){

String temp=t();

t("");

}

});

try {

t(t()+"n我说:"+temp);

try {

TF(temp);

if(("bye")){

();

();

}

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

s=new Socket("localhost",5000);//创建自己的Socket对象

out=new DataOutputStream(putStream());//得到输出流,用于发送数据给对方

} catch (UnknownHostException e) {

tackTrace();

} catch (IOException e) {

tackTrace();

}

aultCloseOperation(EXIT_ON_CLOSE);

e(400,300);

ible(true);

}

public ClientFrame(){

super("客户端");

init();

ReceiveThread rt=new ReceiveThread(s,jtaContent);//把本窗口中的Socket对象s和文本区对象jtaContent传递给接收数据的子线程,这样子线程和主程序使用的是同一套对象

();

}

public static void main(String[] args) {

// TODO Auto-generated method stub

ClientFrame cf=new ClientFrame();

}

}

2.使用DatagramSocket和DatagramPacket编写一个两人聊天的程序。

public class UDPTalk extends JFrame{

JLabel lblInput=new JLabel("请输入:");

JTextField txtInput=new JTextField(20);

JButton btnSend=new JButton("发送");

JTextArea jtaContent=new JTextArea(10,20);

JPanel pUp=new JPanel();

String name;

DatagramSocket ds;

int localPort=3000;//本地端口号,将来从这个端口往外发送数据和接收对方的发来的数据。默认值是3000,将来由构造方法传入真正使用的端口号

int remotePort=5000;//远程端口号,将来往对方的这个端口号发送数据。默认值是5000,将来由构造方法传入真正使用的端口号

Container c;

DatagramReceive dc;//接收数据的子线程

private void init(){

c=tentPane();

out(new BorderLayout());

out(new FlowLayout());

(lblInput);(txtInput);(btnSend);

(pUp,);

(jtaContent,);

ionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

String temp=t();

("n我说:"+temp);

byte[] buf=es();

try {

DatagramPacket dp=new

DatagramPacket(buf,,ame("localhost"),remotePort);

(dp);

if(().equals("bye")){

g(false);

();

}

} catch (UnknownHostException e1) {

n("创建DatagramPacket出错,原因可能是主机名不存在");

} catch (IOException e2) {

n("数据发送错误,可能的原因是对方地址和端口号错误");

}

}

});

aultCloseOperation(EXIT_ON_CLOSE);

e(400,400);

ible(true);

}

public UDPTalk(String name,int localPort,int remotePort){

super(name);

ort=localPort;

Port=remotePort;

init();

try {

ds=new DatagramSocket(localPort);

//在这里创建子线程,启动接受数据线程,将本窗口的ds和jtaContent传递给接收数据的线程

dc=new DatagramReceive(name,ds,jtaContent);

();

} catch (SocketException e) {

n("DatagramSocket创建出错,原因可能是端口号"+localPort+"不能使用");

}

}

public static void main(String args[]){

}

}

//talkA的标题显示主机A,本地端口是3000,远程端口是5000

UDPTalk talkA=new UDPTalk("主机A",3000,5000);

//talkB的标题显示主机B,本地端口是5000,远程端口是3000

UDPTalk talkB=new UDPTalk("主机B",5000,3000);

第13章

1. 什么是JDBC?

JDBC(Java Database Connectivity)是Java程序如何操作数据库的规范。在Java编写的程序中,程序员通过使用JDBC API,可以用标准SQL语句访问几乎任何一种数据库;特定数据库厂商通过实现JDBC API生产的JDBC驱动程序完成某个具体数据库的实际操作。

2. JDBC驱动程序分为几种?现在常用的是哪一种?

JDBC驱动程序有下列4种类型:JDBC-ODBC桥驱动程序、部分 Java 驱动程序、中间件驱动程序、纯Java驱动程序。

现在常用的是纯Java驱动程序。

3. 请写出使用JDBC 3.0访问数据库5个步骤的文字描述。

加载驱动程序,创建连接对象,创建语句对象(例如Statement)执行SQL语句,遍历结果集对象(可选),依次关闭资源对象。

4. 根据本章MySQL数据库testDB中的表user设计,请写出Java代码实现使用Statement查询user表id为1的记录。

public static void getUserById() throws ClassNotFoundException, SQLException {

e(driverName);

Connection conn = nection(url, dbUser, dbPassword);

String sql = "select * from user where id = 1";

Statement stmt = Statement();

ResultSet rs = eQuery(sql);

if (()) {

int id = ("id");

String name = ing("name");

String password = ing("password");

String sex = ing("sex");

Date birthday = e("birthday");

n("id=" + id + ";name=" + name + ";password="

+ password + ";sex=" + sex + ";birthday="+ birthday);

}

();

();

();

}

5. 根据本章MySQL数据库testDB中的表user设计,请写出Java代码实现使用PreparedStatement查询user表id为1的记录。

public static void getUserById() throws ClassNotFoundException, SQLException {

e(driverName);

Connection conn = nection(url, dbUser, dbPassword);

String sql = "select * from user where id = ?";

PreparedStatement ps = eStatement(sql);

(1,1);

ResultSet rs = eQuery();

if (()) {

int id = ("id");

String name = ing("name");

String password = ing("password");

String sex = ing("sex");

Date birthday = e("birthday");

n("id=" + id + ";name=" + name + ";password="

+ password + ";sex=" + sex + ";birthday="+ birthday);

}

();

();

();

}

6. 编写存储过程getAgeById,要求存储过程只有一个参数inIdOutAge且该参数为输入输出(INOUT)类型。作为输入参数时,inIdOutAge表示用户id,作为输出参数时inIdOutAge表示查询结果age。

CREATE DEFINER=`root`@`localhost` PROCEDURE `getAgeById`(INOUT `inIdOutAge` int)

BEGIN

SELECT age INTO `inIdOutAge` FROM `user` WHERE id = inIdOutAge;

END

7. 使用JDBC完成对存储过程getAgeById的调用,要求将输出参数值打印到控制台。

public static void getAgeById() {

Connection conn = null;

CallableStatement cs = null;

ResultSet rs = null;

try {

// 存储过程语句格式:{call getAgeById(?)}

conn = nection();

cs = eCall("{call getAgeById(?)}");

(1, 1);

erOutParameter(1, R);

e();

//int age = (1);

int userAge = ("inIdOutAge");

n(userAge);

} catch (SQLException e) {

tackTrace();

} finally {

(rs, cs, conn);

}

}

8. 编写一个类CRUDTestByPSAndDBConnection,使用数据库帮助类DBConnection,完成使用PreparedStatement实现增删改查。

package ;

import tion;

import ;

import edStatement;

import Set;

import eption;

import ar;

import ianCalendar;

import ection;

public class CRUDTestByPSAndDBConnection {

public static void main(String[] args) throws SQLException {

// add();

// listAll();

// update();

// delete();

}

public static void add() throws SQLException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

// 2、获得连接对象

conn = nection();

// 定义sql语句

String sql = "insert into user(id,name,password,sex,age,birthday)"

+ "values(?,?,?,?,?,?)";

// 3、创建语句对象

ps = eStatement(sql);

(1, 2);

ing(2, "张三");

ing(3, "zhangsan123");

ing(4, "man");

(5, 20);

Calendar c = new GregorianCalendar();

(1998, 0, 1);

e(6, new (eInMillis()));

eUpdate();

// 4、遍历结果集(此处不需要)

} finally {

// 5、关闭资源对象

(rs, ps, conn);

}

}

public static void update() throws SQLException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

}

// 2、获得连接对象

conn = nection();

// 定义sql语句

String sql = "update user set name = ? where id = ?";

// 3、创建语句对象

ps = eStatement(sql);

ing(1, "张三");

(2, 1);

eUpdate();

// 4、遍历结果集(此处不需要)

} finally {

// 5、关闭资源对象

(rs, ps, conn);

}

// 删除user表id=1的记录

public static void delete() throws SQLException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

}

// 2、获得连接对象

conn = nection();

// 定义sql语句

String sql = "delete from user where id = ?";

// 3、创建语句对象

ps = eStatement(sql);

(1, 1);

eUpdate();

// 4、遍历结果集(此处不需要)

} finally {

}

// 5、关闭资源对象

(rs, ps, conn);

// 查询user表的全部记录

public static void listAll() throws SQLException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

// 2、获得连接对象

conn = nection();

// 定义sql语句

String sql = "select * from user";

// 3、创建语句对象

ps = eStatement(sql);

rs = eQuery();

// 4、遍历结果集

while (()) {

int id = ("id");

String name = ing("name");

String password = ing("password");

String sex = ing("sex");

Date birthday = e("birthday");

n("id=" + id + ";name=" + name + ";password="

+ password + ";sex=" + sex + ";birthday="+ birthday);

}

} finally {

// 5、关闭资源对象

(rs, ps, conn);

}

}

}

9. 使用JDBC事务管理完成向数据库user表插入一条记录并更新该记录的age字段值。

编写一个类UseJDBC4,使用JDBC4.X完成表user的增删改查。

// 使用JDBC事务管理完成向数据库user表插入一条记录并更新该记录的age字段值

public static void test() throws SQLException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

conn = nection();

// 事务开始

oCommit(true);

String sql = "insert into user"

+ "(id,name)"

+ " values(?,?)";

ps = eStatement(sql);

(1, 1);

ing(2, "zhangsan");

eUpdate();

sql = "update user set age = ? where id = ?";

ps = eStatement(sql);

ing(1, 20);

(2, 1);

eUpdate();

//手动提交事务

();

} catch(SQLException e){

//事务中某项操作不成功事务回滚

ck();

}finally {

(rs, ps, conn);

}

}

// 编写一个类UseJDBC4,使用JDBC4.X完成表user的增删改查

package ;

import tion;

import Manager;

import edStatement;

import Set;

import eption;

public class UseJDBC4{

public static void main(String[] args) throws ClassNotFoundException, SQLException {

add();

}

public static void listAll() throws SQLException {

Connection conn = getConnection();

String sql = "select id,name from user";

try (PreparedStatement ps = eStatement(sql)) {

ResultSet rs = eQuery();

while (()) {

n(("id") + "t" + ing("name"));

}

} catch (SQLException e) {

tackTrace();

// TODO: handle exception

}

();

}

public static void update() throws SQLException {

Connection conn = getConnection();

}

String sql = "update user set name= ? where id = ?";

try (PreparedStatement ps = eStatement(sql)) {

ing(1, "updateUser");

eUpdate();

();

} catch (SQLException e) {

tackTrace();

}

public static void add() throws SQLException {

Connection conn = getConnection();

String sql = "insert into user(id,name) values(?,?);";

try (PreparedStatement ps = eStatement(sql)) {

(1, 1);

ing(2, "Mike");

eUpdate();

();

} catch (Exception e) {

tackTrace();

}

}

public static void delete() throws SQLException {

Connection conn = getConnection();

String sql = "delete from user where id = ?";

try (PreparedStatement ps = eStatement(sql)) {

(1, 1);

eUpdate();

();

} catch (Exception e) {

tackTrace();

}

}

public static Connection getConnection() {

Connection connection = null;

try {

e("");

String url = "jdbc:mysql://localhost:3306/testDB";

String dbUser = "root";

String dbPassword = "root";

connection = nection(url, dbUser, dbPassword);

} catch (ClassNotFoundException e) {

}

}

tackTrace();

} catch (SQLException e) {

tackTrace();

}

return connection;


本文标签: 方法 对象 使用 变量 线程