第六章课后习题
1.this和super各有几种用法?
1.子类的构造函数如果要引用super的话,必须把super放在函数的首位。
2.子类中的同名成员变量或方法隐藏了父类的成员变量或方法,需要用到super。
3.用super直接传递参数。
2.子类对象实例化的具体过程是什么?
1.子类在构造对象时候,必须访问父类的构造函数,为了完成这个必须的动作,就在子类的构造函数中加入了super()语句。
2.如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中哪个构造函数,否则子类无法完成初始化。
3.在构造函数生效之前,程序会先执行静态的成员活方法的初始化。
3.类的域变量和方法中定义的局部变量在初始化上有何区别?
类的域变量在类初始化的时候就开始创建了,而方法中的变量是在调用到该方法时,才会为该变量创建。
4.模仿形成抽象类的过程,自选角度,形成一个自己的抽象类,并在程序的类继承和引用中体现抽象类的作用。
`
abstract class Animal {
private int a = 10;
public abstract void bark(); //如果没有此抽象方法,但是class前有absract修饰,也是抽象类,也不能实例化
public void say() { //普通成员方法
System.out.println("我是抽象类中的非抽象方法,此抽象类中的私有成员变量a= " + a);
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
class Dog extends Animal{
public void bark() { //子类实现Animal的抽象方法
System.out.println("汪汪~汪汪~");
System.out.println("我是子类,只有通过super.getA()调用父类的私有变量a:" + super.getA());
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.say(); //子类继承调用Animal的普通成员方法
dog.bark(); //子类调用已经实现过的方法
}
}`
5.接口有什么作用?自己定义一个接口,并给出实现类和使用类。
接口最直接的好处就是提供了一个统一的操作方法名,然后同样的方法名在不同的类中可以有不同的具体实现过程,这样的结果就是在操作实现了该接口的类的对象时,不用去事先了解该方法的名字,而采用统一的名字进行调用。
interface A{
// 定义接口A
public abstract void print() ; // 定义抽象方法print()
}
class B implements A { // 定义子类,实现接口
public void print(){ // 覆写抽象方法
System.out.println("Hello World!!!") ;
}
}
public class Test{
public static void main(String args[]){
A a = new B() ; // 通过子类为抽象类实例化
a.print() ;
}
}
6.抽象类与接口的异同点是什么?
相同点:
1、不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、都有自己的声明,可以引用子类或实现类对象
不同点 :
1、抽象类可以有域变量,接口没有,只能是静态常量。
2、抽象类可以有具体方法;接口全是抽象方法。
3、抽象类实现靠子类继承,接口靠实现类。
7.引用比较方法有哪些?
1.equals方法比较。
2.使用“==”进行比较。
3.使用instanceof比较引用类型
8.内部类的作用是什么?什么情况下使用匿名内部类?
作用:
1.内部类可以很好的实现隐藏。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以。
2.内部类拥有外围类的所有元素的访问权限。
3.可是实现多重继承。
4.可以避免修改接口而实现同一个类中两种同名方法的调用。
匿名内部类:
匿名内部类是内部类的一种特殊情况。它只有一个实例,而且没有引用。所以,一般在能用内部类实现,但是实例只用一次的情况下使用它(可以减少资源开销)。
9.不上机,判断下面程序的输岀结果。
class X {
Y b = new Y();
X() {
System.out.println(“X”);
}
}
class Y {
Y() {
System.out.println(“Y”);
}
}
public class Z extends X{
Y y = new Y();
Z() {
System.out.println(“Z”);
}
public static void main(String[] args) {
new Z();
}
}
A. Z B. YZ C. XYZ D. YXYZ
答案:D
解析:执行new Z();后,进入Z类,首先实现父类X,实现X时又由于Y b = new Y();先实现Y,于是输出Y,完毕后回到X,输出X,再回到Z类,执行Y y = new Y();输出Y,最后输出Z。
10.什么是数据隐藏?如何证明子类对父类同名方法进行重新定义,只能是方法的覆盖,而不是方法的隐藏?
1.在子类对父类的继承中,如果子类的成员变量和父类的成员变量同名,此时称为子类隐藏(override)了父类的成员变量。
2.覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同。
隐藏:父类和子类拥有相同名字的属性或者方法( 方法隐藏只有一种形式,就是父类和子类存在相同的静态方法)时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。
11.A1、A2分别是具体类A的子类,A3为A1的子类,A1、A2之间的关系为平行类, 如图6.15所示。下面的代码为连续的程序片段,请问哪些是正确的?
A a = new A();
a = new A1();
a = new A2();
a = new A3();
A1 a1 = new A3 ();
A3 a3 = a1; //×
A2 a2 = new A1(); //×
a3 = new A2(); //×
12.借助JDK帮助,编写程序实现这样的功能:Applet当中的TextField,每输入任一字符,在一个label当中都能动态跟踪刷新。
import java.applet.;
import java.awt.;
import java.awt.event.*;
public class MyApplet extends Applet implements ActionListener{
private TextField input;
private double d=0.0;
//进行初始化工作,产生对象,加入监听者
public void init(){
input = new TextField(10);
//myApplet是容器,input是组件,调用add使input嵌入容器
add(input);
input.addActionListener(this); //向TextField注册监听器
}
public void paint(Graphics g){
g.drawString("您输入了数据"+d,10,50);
}
public void actionPerformed(ActionEvent e) {
d=Double.valueOf(input.getText()).doubleValue();
//进行刷新,调用paint()方法
repaint();
}
}
第七章课后习题
1.“程序中凡是可能出现异常的地方必须进行捕获或拋出”,这句话对吗?
不对。
异常分两类,runtime异常和非runtime异常。
runtime异常,比如NullPointException等,这一类你不在程序里面进行try/catch,编译不会出错。
非runtime异常,比如SqlException等或自定义的exception,这一类在程序里不进行try/catch或throws,编译就会出错。
2自定义一个异常类,并在程序中主动产生这个异常类对象。
public class SE extends Exception
{
SE(String msg){
super(msg); //调用Exception的构造方法
}
static void throwOne() throws SE{
int a = 1;
if (a==1){ //如果a为1就认为在特定应用下存在异常,改变执行路径,抛出异常
throw new SE("a为1");
}
}
public static void main(String args[]){
try{
throwOne();
}catch(SE e){
e.printStackTrace();
}
}
}
3.借助JDK帮助,请列举发生NullPointerException异常的一些情况。
当应用程序试图在需要对象的地方使用 null 时,抛出该异常。这种情况包括:
被调用方法的对象为null。
访问或修改一个null对象的字段。
求一个数组为null对象的长度。
访问或修改一个数组为null对象中的某一个值。
被抛出的值是null并且是一个Throwable的子类。
当你用null对象进行synchronized代码块。
NullPointerException 是 RuntimeException 的子类,因此,Javac 编译器并不会强迫你使用 try-catch 代码块来捕获该异常。
4.不执行程序,指出下面程序的输出结果;如果将黑体代码去掉,写出输出结果;如果再将斜体代码去掉,写出输出结果。
public class Test{
public static void aMethod() throws Exception{
try{
throw new Exception();
}
catch(Exception e){
System.out.println("exception000");
}
finally{
System.out.println("exception111");
}
}
public void main(String[] args){
try{
aMethod();
}catch(Exception e){
System.out.println("exception");
}
System.out.println("finished");
}
}
输出:
exception000
exception111
finished
去黑体输出:
exception111
exception
finished
去斜体输出:
exception000
finished
不执行程序,指出下面程序的输出结果。
public class Test{
public static String output ='';
public static void f(int i){
try{
if(i==1) {throw new Exception();}
output += "1";
}
catch(Exception e){
output += "2";
return;
}
finally{output += "3";}
output += "4";
}
public static void main(String args[]){
f(0);
f(1);
System.out.println(Test.output);
}
}
结果:13423
6.编写一个程序方法,对空指针异常、除数为零异常给出出错的中文提示。当有新异常发生时,可扩展该方法中的代码进行统一处理。
public class t{
public static void main(String[] args) {
try {
String s = null;
System.out.println(s.charAt(0));//空指针异常
}catch (NullPointerException e) {
System.out.println("空指针异常");
}catch (ArithmeticException e) {
System.out.println("计算异常");
}catch (Exception e) {
System.out.println("其他异常");
e.printStackTrace();
}
}
7.从屏幕输入10个数,在输入错误的情况下,给出相应的提示,并继续输人。在输入完成的情况下,找到最大最小数。
import java.util.Scanner;
public class t {
private static Scanner sc;
public static void main(String[] args) {
int index = 0;
int[] array = new int[10];
int max,min;
while (true) {
if (index == array.length) { break;}
sc = new Scanner(System.in);
System.out.print("输入" + (index + 1) + ":");
try {
array[index] = sc.nextInt();
index++;
}
catch (Exception e) {System.out.println("输入错误,重新输入!");}
}
max = array[0];
min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {max = array[i];}
if (array[i] < min) {min = array[i];}
}
System.out.println("max = " + max);
System.out.println("min = " + min);
}
}
8.阅读下面程序,TimedOutException为自定义异常,完成指定方法后面的部分。
public void method()throws TimedOutException
{
success= connect();
if(success == -1)
{
throw new TimedOutException();
}
}
第八章课后题
3.String类型有什么特点?
4.String什么时候进行值比较,什么时候进行引用比较?
stringA.equals(stringB);进行值比较
stringA==stringB;进行引用比较
5.String与StringBuffer的区别是什么?如何相互转化?
区别:
运行速度 :String
相互转换:
String转换成StringBuffer:构造方法和append方法;
public class StringAndStringBufferSwitch {
public static void main(String[] args) {
//String -> StringBuffer
//创建一个String对象
String str = "Hi Java!";
System.out.println(str);
//方式一:构造方法
StringBuffer buffer = new StringBuffer(str);
System.out.println(buffer);
//方式二:通过append方法
StringBuffer buffer2 = new StringBuffer();
buffer2.append(str);
System.out.println(buffer2);
}
StringBuffer转换成String:
StringBuffer sb1 = "sb"
String s1 = String(sb1)
第九章课后习题
1.线程和进程的联系和区别是什么?
区别:
1.进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是系统进行资源分配和调度的一个独立单位。
2.线程是进程的一个实体,是CPU调度和分配的基本单位。线程基本不拥有系统资源,与同一个进程的其他线程共享进程中所拥有的所有资源。
联系:
1.一个进程可以包括多个线程
2.什么是前台线程,什么是后台线程?
应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束
3.创建线程有几种方法?它们之间的区别是什么?
第一种方式:使用Runnable接口创建线程
1.可以实现多个线程资源共享
2.线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法
第二种方式:直接继承Thread类创建对象
1.Thread子类无法再从其它类继承(java语言单继承)。
2.编写简单,run()方法的当前对象就是线程对象,可直接操作
4.线程的生命周期有哪些状态?哪些方法可以改变这些状态?
1、创建状态:线程对象已经创建,还没有在其上调用start()方法。
2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4、阻塞状态:这是线程有资格运行时它所处的状态。如执行了join/sleep/wait方法,会让出CPU,只有当引起阻塞的原因消除时,线程才能转入就绪状态。
5、死亡态:当线程的run()方法完成时就认为它死去。或者抛出一个未捕获到的Exception或Error
5.什么是线程安全?为什么会产生线程安全问题?如何解决线程安全问题?
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
原因是由于不同线程获取到资源时进行运算,但未来得及写入时,线程改变,则另外线程读入的资源就是错误,导致所有线程写入读入不同步。
解决办法:
使用监视器,使用关键字synchronized监视同步代码块,当一个线程获得监视权限时,别的线程就无法获得,保证每时每刻只有一个线程调用某一方法
6.什么是线程的同步通信?同步通信又是如何实现的?
线程同步通信是希望实现两个或多个线程之间的某种制约关系
实现:首先是用监视器synchronized来保证每次只有一个线程调用方法,其次引入一个boolean型标志来判断该线程是否执行或wait,两个线程时使用notify(),多个线程时用notifyAll()来让出监视器并唤醒其他线程。这样就实现了线程之间的关系
7.什么是死锁?
线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁
8.如何让某个对象的A方法内的一个代码块和另一个方法B实现同步?
class acc
{
volatile private int value;
void put(int i)
{
synchronized(this) {
value = value + i;
System.out.println("存入"+i+" 账上金额为:"+value);
}
}
synchronized int get(int i)
{
if (value>i)
value = value - i;
else
{ i = value;
value = 0;
}
System.out.println("取走"+i+" 账上金额为:"+value);
return i;
}
}
class s implements Runnable
{
int a=2000;
private acc a1;
public s(acc a1)
{
this.a1 = a1;
}
public void run()
{
while(a-->0){
a1.put(100);
}
}
}
class f implements Runnable
{
int a=2000;
private acc a1;
public f(acc a1)
{this.a1 = a1 ;}
public void run()
{
while(a-->0){
a1.get(100);
}
}
}
public class t{
public static void main(String[] args){
acc a1 = new acc();
new Thread(new s(a1)).start();
new Thread(new f(a1)).start();
}
}
9.设计一个程序产生两个线程A与B,B线程执行10秒钟后,被A线程中止。
class acc
{
int b=0;
void change(int _a) {b=_a;}
int getb() {return b;}
volatile private int value;
synchronized void put(int i)
{
value = value + i;
System.out.println("存入"+i+", 账上金额为:"+value);
}
}
class s implements Runnable
{
//int a=2000;
private acc a1;
public s(acc a1)
{
this.a1 = a1;
}
public void run()
{
while(a1.getb()==0) {
try {
Thread.sleep(900);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
a1.put(1);
}
System.out.println("10秒已到,停止存钱。stop!");
}
}
class f implements Runnable
{
//int a=20;
private acc a1;
public f(acc a1)
{this.a1 = a1 ;}
public void run()
{
if(a1.getb()==0) {
try {
Thread.sleep(9000);
} catch (InterruptedException e) {}
}
a1.change(1);
}
}
public class t{
public static void main(String[] args){
acc a1 = new acc();
new Thread(new s(a1)).start();
new Thread(new f(a1)).start();
}
}
补充(选做):编写一个基于多线程的生产者/消费者程序,各产生10个生产者和消费者线程,共享一个缓冲区队列(长度自设),生产者线程将产品放入到缓冲区,消费者线程从缓冲区取出产品。
使用synchronized+wait()+notify()/notifyAll()
package java_lang_Object;
import java.util.LinkedList;
/**
* Created by luckyboy on 2018/7/4.
*/
public class ConsumerAndProducer {
public static void main(String[] args){
Storage storage = new Storage();
Producer p1 = new Producer(10,storage);
Producer p2 = new Producer(20,storage);
Producer p3 = new Producer(90,storage);
Consumer c1 = new Consumer(50,storage);
Consumer c2 = new Consumer(30,storage);
Consumer c3 = new Consumer(40,storage);
p1.start();
p2.start();
p3.start();
c1.start();
c2.start();
c3.start();
}
}
//Storage提供consume()和produce()供Consumer和Producer调用
class Storage{
private final int MAX_SIZE = 100;//
private LinkedList<Object> list = new LinkedList<Object>();//
public void produce(int num){
synchronized (list){
//当仓库的剩余容量不足时
while(list.size() + num >MAX_SIZE){
System.out.println(Thread.currentThread().getName()+" 要生产的数量 == "+ num +" 仓库的数量 == "+list.size()+" 不能生产,等待Consumer消费 ");
try{
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i = 1;i <= num;i++){
list.add(new Object());
}
System.out.println(Thread.currentThread().getName()+" 已经生产产品数 == "+ num+" 当前的仓储量为 == "+list.size());
list.notifyAll();
}
}
public void consume(int num){
synchronized (list){
//当仓库的物品剩余容量不足时
while(list.size() - num <0){
System.out.println(Thread.currentThread().getName()+" 要消费的数量 == "+ num +" 仓库的数量 == "+list.size()+" 不能消费,等待Producer生产");
try{
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i = 1;i <= num;i++){
list.remove();
}
System.out.println(Thread.currentThread().getName()+" 已经消费的产品数 == "+ num+" 当前的仓储量为 == "+list.size());
list.notifyAll();
}
}
public LinkedList<Object> getList() {
return list;
}
public void setList(LinkedList<Object> list) {
this.list = list;
}
}
//生产者
class Producer extends Thread {
private int num;
private Storage storage;
public Producer(int num,Storage storage){
this.storage = storage;
this.num = num;
}
public void setNum(int num){
this.num = num;
}
@Override
public void run(){
this.storage.produce(num);
}
}
//消费者
class Consumer extends Thread{
private int num;
private Storage storage;
public Consumer(int num,Storage storage){
this.num = num;
this.storage = storage;
}
@Override
public void run(){
this.storage.consume(this.num);
}
}
输出结果
Thread-1 已经生产产品数 == 20 当前的仓储量为 == 20
Thread-2 要生产的数量 == 90 仓库的数量 == 20 不能生产,等待Consumer消费
Thread-0 已经生产产品数 == 10 当前的仓储量为 == 30
Thread-5 要消费的数量 == 40 仓库的数量 == 30 不能消费,等待Producer生产
Thread-2 要生产的数量 == 90 仓库的数量 == 30 不能生产,等待Consumer消费
Thread-4 已经消费的产品数 == 30 当前的仓储量为 == 0
Thread-3 要消费的数量 == 50 仓库的数量 == 0 不能消费,等待Producer生产
Thread-2 已经生产产品数 == 90 当前的仓储量为 == 90
Thread-5 已经消费的产品数 == 40 当前的仓储量为 == 50
Thread-3 已经消费的产品数 == 50 当前的仓储量为 == 0
第十四章课后习题答案
3.完成下面方法中的代码,要求建立一个缓冲区,将字节输入流中的内容转为字符串。static String loadStream(InputStream in) throws IOException {…}
import java.io.*;
public class hellojava {
static String loadStream(InputStream in) throws IOException {
StringBuffer buffer = new StringBuffer();
int n = 1,i=10;//但局限在于i已经确定了读取字节的大小最多为10个字节
byte[] buf = new byte[n];//缓冲区,大小为1字节
while(i-->0) {
in.read(buf,0,n);
buffer.append(new String(buf)); //连接一个字符串
}
return new String(buffer);
}
public static void main(String[] args) throws IOException {
InputStream in = new BufferedInputStream(System.in);
String test=loadStream(in);
System.out.println("result=: "+test);
}
}
4.编写程序,将一个字符串转为字节数组输入流,将这个流中所有小写字母换成大写字母并写入字节数组输出流中,再将数组输出流转为字符串。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class hellojava {
public static void main(String[] args) {
String str = "Hello java"; //源字符串
ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes());
//字节数组输出流
ByteArrayOutputStream out = new ByteArrayOutputStream();
int b = -1;
while((b = in.read()) != -1){
//把小写字母转换成大写字母
if(b >= 97 && b <= 122){
b -= 32;
}
//写回到字节数组输出流中
out.write(b);
}
System.out.println();
String s =out.toString();
System.out.println(s);
}
}
5.完成下面方法中的代码,方法中的参数为一个文本文件的名称,要求将文件中的内容转为字符串。static public String loadFile(String filename){…}
package hellojava;
import java.io.*;
public class hellojava {
static public String loadFile(String filename) {
File file = new File( filename );//建立文件对象
try {
Reader in = new FileReader( file );//建立读文件对象
long fileLength = file.length();
char[] ch = new char[(int)fileLength]; //开辟一次读入的大小
in.read(ch);
in.close();
return new String(ch);//变为字符串
} catch(IOException ioe) {
return null;
}
}
public static void main(String[] args) {
String fname = "t.txt";
String test=loadFile(fname);//调用方法
System.out.println(test);
}
}
6.完成下面方法中的代码,将字符串contents中的内容写入文件filename中。static public boolean saveFile(String filename,String contents){…}
import java.io.*;
public class hellojava {
static public boolean save(String filename, String contents) {
try {
File file = new File( filename );
if(!file.exists()) {//判断该txt是否存在
file.createNewFile();//不存在就在当前目录下新建一个
}
Writer wtr = new FileWriter( file );
char[] ch = contents.toCharArray();//把字符串转为字符数组
wtr.write(ch);
wtr.close();
return true;
} catch(IOException ioe) {
return false;
}
}
public static void main(String[] args) throws IOException {
String name = "test.txt";//给定文件名
String contents = "hellojava";//给定写入的字符串
if(save(name,contents))System.out.println("save!");
}
}
7.socket套接字有一个方法getInputStream(),其含义是得到从网络上传过来的数据流。现要求编写一段程序,将接收的数据存入文件。
客户端:
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args)throws IOException {
Socket socket = new Socket("127.0.0.1",8080);
OutputStream out = socket.getOutputStream();
int i =20;
while(i-->0)
{
out.write("HELLO".getBytes());
out.flush();
}
System.out.println("已经发送!");
out.close();
socket.close();
}
}
服务器端:
import java.io.*;
import java.net.*;
public class Server{
public static void main(String[] args)throws IOException {
ServerSocket server = new ServerSocket(8080);
//获得与服务器相连的套接字对象 套接字:绑定ip地址和端口号的网络对象
Socket socket = server.accept();
//查看该地址文件夹是否存在,如果不存在,创建一个
String name = "t.txt";
File file = new File(name);
if(!file.exists()){
file.createNewFile();//文件不存在
System.out.println("文件创建");
}
InputStream in = socket.getInputStream();
FileOutputStream fout = new FileOutputStream(name);
byte[] data = new byte[5];
int len = 0;
while((len = in.read(data)) != -1)
{
fout.write(data, 0, len);
fout.write("\r\n".getBytes());
}
System.out.println("已经上传");
server.close();
fout.close();
}
}
8.编写程序实现文件查找功能。提供两个参数,第一个参数为查找的起始路径,第二个参数为要查找的文件名称。如果找到,则给出文件的完整路径,否则提示文件不存在。
package hellojava;
import java.io.File;
public class hellojava
{
String path = null;
public String searchFile(File dir, String fileName)
{
if(dir.isFile())//dir为文件
{
if(dir.getName().equals(fileName))//dir为一个文件,和要找的文件比对
path = dir.getAbsolutePath();
}
if (dir.isDirectory())//dir为文件夹
{
File[] files = dir.listFiles();
File f ;//遍历所有文件或者文件夹
for (int i=0;i<files.length;i++ ){
f = files[i];
path = searchFile(f, fileName);
}
}
return path;
}
public static void main(String[] args) {
File dir = new File("E:/");
String fileName = "test.dat"; //自己修改个文件名
if (!dir.exists())
{
System.out.println("目录不存在:" + dir);
System.exit(0);
}
String path = new hellojava().searchFile(dir,fileName);
if(path!=null)
System.out.println("文件完整路径:" + path);
else
System.out.println("不存在此文件");
}
}
15-6.利用串行化技术和Socket通信,将一个客户端构造的对象传送到服务器端,并输出该对象的属性值。
import java.io.Serializable;
public class User implements Serializable{
String Name;
String Password;
User()//默认构造函数
{
Name="null";
Password="00000";
}
User(String name,String password)//带参数的构造函数
{
Name=name;
Password=password;
}
void setName(String name) {Name=name;}
void setPassword(String password) {Password=password;}
String getName() {return Name;}
String getPassword() {return Password;}
}
客户端:
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException{
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 8080);
} catch (IOException e) {
e.printStackTrace();
}
User u1 = new User();
u1.setName("Tommy");
u1.setPassword("1234567"); //赋值
//把对象串行化为可输出的形式,输入到Socket的输出流里面
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(u1);//以串行化方式写入这个对象
System.out.println("successful!");
out.flush();
out.close();
}
}
服务器端:
import java.io.*;
import java.net.*;
public class MultiTalkServer {
public static void main(String[] args) throws ClassNotFoundException, IOException {
ServerSocket server;
Socket socket = null;
try {
server = new ServerSocket(8080);
socket = server.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
System.out.println("连接成功!");
User u2 = (User) in.readObject();
System.out.println("Name: "+ u2.getName() + " Password: " + u2.getPassword());
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
第十五章课后习题答案
第五题
5.利用URLConnetction对象编写程序返回某网站的首页,并将首页的内容存放到文件当中
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class s {
public static void main(String[] args) throws IOException {
URL url= new URL("https://www.baidu.com/");
URLConnection con = url.openConnection();
BufferedReader is= new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
FileOutputStream fos = new FileOutputStream("./test.txt");
String line;
while((line = is.readLine()) != null ) {
line = line + "\n";
fos.write(line.getBytes("UTF-8"));
fos.flush();
}
is.close();
fos.close();
}
}
基于TCP的通信
客户端:
import java.io.*;
import java.net.Socket;
public class TalkClient {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 8080);//本机地址
} catch (IOException e) {
System.out.println("Can't not listen to " + e);
}
try {
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));//构建各种输入输出流对象
BufferedWriter os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String readLine;
while(!(readLine = sin.readLine()).equals("bye")) {
os.write(readLine + "\n");
os.flush();
System.out.println("Server " + ": " + is.readLine());
}
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器 + 线程:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
class ServerThread extends Thread{
Socket socket = null;
int clienNum;
public ServerThread(Socket socket, int num){
this.socket = socket;
clienNum = num + 1;
}
public void run(){
try {
String readLine;
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));//构建各种输入输出流对象
BufferedWriter os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("connected with: " + socket);
System.out.println("Client " + clienNum + ": " + is.readLine());
readLine = sin.readLine();
while(!readLine.equals("bye")){
os.write(readLine + "\n");
os.flush();
System.out.println("Client " + clienNum + ": " + is.readLine());//添加是哪个客户端发过来的消息
readLine = sin.readLine();
}
os.close();
is.close();
socket.close();
} catch (IOException e) {
System.out.println("Error: " + e);
}
}
}
public class MultiTalkServer {
private static int clientNum = 0;
public static void main(String[] args) throws IOException {
ServerSocket server = null;
boolean listening = true;
try {
server = new ServerSocket(8080);//设置监听端口
} catch (IOException e) {
System.out.println("Could not listen on port: 4700");
System.exit(-1);
}
while(listening){
new ServerThread(server.accept(), clientNum).start();//启动新线程
clientNum++;
}
server.close();
}
}
仿照例15.5,编写完整的基于数据报的多客户/服务器通信程序
客户端(只能启动一个,这是数据报的规定,但启动多个不会报错):
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException{
DatagramSocket socket=new DatagramSocket();
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
String readLine;
InetAddress address=InetAddress.getByName("127.0.0.1");
while(!(readLine = sin.readLine()).equals("bye")) {
byte[] buf = readLine.getBytes();
DatagramPacket packet=new DatagramPacket(buf, buf.length, address, 8080);
socket.send(packet); //发送
buf = new byte[256];
//创建新的DatagramPacket对象,用来接收数据报
packet=new DatagramPacket(buf,buf.length);
socket.receive(packet); //接收
buf = packet.getData();
String received=new String(buf);
System.out.println("Sever: "+received );
}
socket.close(); //关闭套接口
}
}
服务器 + 线程:
import java.io.*;
import java.net.*;
class ServerThread extends Thread//服务器线程
{
protected DatagramSocket socket=null;
protected BufferedReader in=null;//用来读文件的一个Reader
protected boolean flag=true;//标志变量,是否继续操作
public ServerThread() throws IOException {//无参数的构造函数
this("ServerThread");
}
public ServerThread(String name) throws IOException {
super(name); //调用父类的构造函数
socket=new DatagramSocket(8080);
in= new BufferedReader(new InputStreamReader(System.in));
}
public void run() //线程主体
{
while(flag) {
try{
byte[] buf=new byte[1024]; //创建缓冲区
DatagramPacket packet=new DatagramPacket(buf,buf.length);
//由缓冲区构造DatagramPacket对象
socket.receive(packet); //接收数据报
//打印出客户端发送的内容
System.out.println("Client : "+new String(packet.getData()));
//从屏幕获取输入内容,作为发送给客户端的内容
String dString= in.readLine();
//如果是bye,则向客户端发完消息后退出
if(dString.equals("bye")){flag=false;}
buf=dString.getBytes();
InetAddress address=packet.getAddress();
int port=packet.getPort(); //端口号
//根据客户端信息构建DatagramPacket
packet=new DatagramPacket(buf,buf.length,address,port);
socket.send(packet); //发送数据报
}catch(IOException e) { //异常处理
e.printStackTrace(); //打印错误栈
flag=false; //标志变量置false,以结束循环
}
}
socket.close(); //关闭数据报套接字
}
}
public class Server{
public static void main(String args[]) throws java.io.IOException
{
new ServerThread().start();
}
}
第十章课后习题答案
T8.如何实现集合对象排序?定义一个复数类并按照复数的实部大小对复数对象进行排序。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class url{
private double x;
private double y;
public double getX() {return x;}
public void setX(double x) {this.x = x;}
public double getY() {return y;}
public void setY(double y) {this.y = y;}
public Plural() {x = 0; y = 0;}
public Plural(double x, double y) {this.x = x; this.y = y;}
public void show() {
if (y == 0)
System.out.println(x);
else if(y<0)
System.out.println(x + " - " + -y + "i");
else
System.out.println(x + " + " + y + "i");
}
}
class urlComparator implements Comparator<url> {
@Override
public int compare(url o1, url o2) {
return o1.getX() < o2.getX() ? 1 : -1;
}
}
public class test {
public static void main(String[] args) {
ArrayList<Plural> lst = new ArrayList<>();
lst.add(new url(0, 2.3));
lst.add(new url(-5, 4));
lst.add(new url(-1.2, -3));
lst.add(new url(1, 0));
Collections.sort(lst, Collections.reverseOrder(new urlComparator()));
//获取要不要交换
for(Plural p : lst)
p.show();
}
}
T10 .对第7章第6题进行适当改造,将异常类型与中文提示存储在一种集合类当中,从而实现相应的功能。
import java.util.HashMap;
class EC{
public HashMap<Class, String> hashm = new HashMap<>();
public EC() {
hashm.put(NullPointerException.class, "空指针异常");
hashm.put(ArithmeticException.class, "除数为0");
}
public void add(Class c, String s) {
hashm.put(c, s);
}
}
public class s {
public static void main(String[] args) {
EC ec= new EC();
Class c = NullPointerException.class;
System.out.println(ec.hashm.containsKey( c));
}
}
第十六章课后习题
T1.使用JDBC来操作数据库通常包含哪几个步骤?
T2.如何载入JDBC driver?
第一步,先去官网下载JDBC驱动并解压,下载链接: https://dev.mysql.com/downloads/connector/j/
第二步,打开你的idea工程,按ctrl+alt+shift+s(打开Project Structure),Modules —>>选中–>>点击右侧的+号——>选第一个jars of directories,找到你刚刚解压缩的位置,选中文件mysql-connector-java-5.1.42-bin.jar——>点击确定
第三步,查看Extermal libraries中是否有mysql-connector-java-5.1.42-bin.jar驱动
T3.java.sql包中的主要接口connection,statement和resultset之间是什么关系?
JDBC是由一系列连接(Connection)、SQL语句(Statement)和结果集(ResultSet)构成的,其主要作用概括起来有如下3个方面: 建立与数据库的连接。向数据库发起查询请求。处理数据库返回结果。
T4.数据库使用完毕后,要进行哪些关闭操作?
例如将Connection connection, Statement statement,
ResultSet rs这三个对象关闭,即将Connection,Statement,ResultSet对象.close()关闭.