``一 java基础篇
public class Hello {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World"); //println:跟上回车的输出
}
}
ctrl+/:注释 Alt+/:代码提示 shift+向下键:选择下一行
“”中为字符串 全选+Tab将代码缩进
import java.util.Scanner;
public class Hello {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World");
Scanner in = new Scanner(System.in);
System.out.println(in.nextLine());
}
}
import java.util.Scanner;
public class Hello {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World");
// Scanner in = new Scanner(System.in);
// System.out.println(in.nextLine());
System.out.println(“1+2=”+(1+2));
}
}
用 + 可以将字符串连接
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.print("请输入票面")
amount = in.nextInt;
//final amount = 50; //amount被定义成一个常量
int price = in.nextInt(); //price作为一个变量
System.out.println("100-" + price +"="+(100-price));
}
}
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.print("请输入票面金额");
int amount = in.nextInt();
System.out.print("请输入银行卡金额");
int price = in.nextInt();
System.out.println("您的金额剩余" + "=" + (amount+price));
}
}
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
int balance = 0 ;
while(true){
System.out.print("请输入票面金额");
int amount = in.nextInt();
balance = balance+amount;
if(balance>10){
Scanner in = new Scanner(System.in);
System.out.print("请输入银行卡金额");
int price = in.nextInt();
System.out.println(balance + "-" + price + "=" + (amount+price)); //字符与整型连接要用加号
balance = 0;
}
//相除if条件要跟分母大于零
}
}
}
//java中两个整数相除得数一定是整数,如果一个是浮点数则结果也为浮点数(double型)
单目取正(负):a*-b 自右向左顺序
强制类型转换:转换成整型 : (int)(***********)将右侧一堆转换成左侧
Scanner in = new Scanner(System.in);
System.out.print(“请输入票面金额”);
int amount = in.nextInt();
System.out.print(amount >= 10); 大于等于10输出true
所有关系运算符优先级比算术优先级低但比赋值优先级高
判断是否相等的运算符==,!=的优先级比其他的低 ,而连续的关系运算是从左到右进行的
判断两个浮点数是否相等: Math.abs(f1-f2)<1e-6
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int amount= in.nextInt();
int Count = 0; //判断一个数字得位数。验证:(试边界数字),0是有问题,采用
do-while 语句(第一次不管忙不满足条件都可以可以进循环体)
do
{
amount = amount/10;
Count = Count + 1;
} while(amount>0);
System.out.println(Count);
}
}
如果要模拟很大次数的循环,可以模拟较少的循环进行推断。
猜数字小游戏:
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
int count = 0;
int a; //a类型需要在外部提前声明
int price = (int)(Math.random()*100+1); [0-10)--->[0-100)-->[1-100]
Scanner in = new Scanner(System.in);
do{
count = count +1;
a = in.nextInt();
if(a>price)
{
System.out.print("猜大了");
}
else
{
System.out.print("猜小了");
}
}while(a!=price);
System.out.print("恭喜!您猜对了!正确数值是"+ price + "您一共猜了" + count + "次");
}
}
整数分解:
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int price = in.nextInt();
int a;
int result = 0;
do{
a= price%10;
price = price/10;
result = result*10+a;
System.out.print(a); //逆序输出,700会输出为·007
}while(price>0); // price最后一位除以10等于0
System.out.print(result); //逆序输出,700会输出为·7
}
}
对于一个循环体,有固定执行次数,用for循环。循环必须要执行一次用do-while。其他情况用while
for(i=0;i<n;i++){}循环n次 factor *=i factor 赋值于1(阶乘)
题干:判断一个数是不是素数
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int amount = in.nextInt();
boolean isPrime = true;
for(int i=2 ; i<amount ; i++)
{
if(amount%i == 0)
{
isPrime = false;
System.out.print("不是素数");
break;
}
}
if(isPrime)
{
System.out.print("这是素数");
}
}
}
逻辑运算优先级: !>&&> || 单目运算符,赋值运算符自右向左
题干:枚举法:
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int amount = in.nextInt();
for(int five = 0;five <= amount/5 ; ++five) //++i意思是先自增后再使用进行操作 {
for(int ten = 0;ten<= amount/10 ; ++ten)
{
for(int twenty = 0;twenty <= amount/20 ; ++twenty)
{
if(five*5+ten*10+twenty*20 == amount)
{
System.out.println(five+"张五元"+ten+"张十元"+twenty+"张20元"+"等于"+amount);
break;
}
}
}
}
}
}
题干:求和:
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int amount = in.nextInt();
double sum = 0.0; //变量要赋初值
int sign = 1;
for(int i=1;i<amount;i++)
{
sum = sum +sign* 1.0/i; //1.0比i要注意转化成浮点型分子要带小数点
sign = -sign;
}
System.out.printf("%.2f",sum); //printf是保证输出中要带条件得输出用逗号分割
}
}
辗转相除法:求两个数最大公约数
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
int r;
int oa = a;
int ob = b;
for(int i=1; i<a&&b ; i++)
{
r = a%b;
a =b;
b = r;
}
System.out.printf(oa+“和"+ob+”的最大公约数为",a); //a与b在计算过程中发生了变化,初始把他们值存入oa,ob
}
}
使用数组求平均数:遍历:
package array;
import java.util.Scanner;
public class Arry {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int count = in.nextInt();
int amount = in.nextInt();
int sum = 0;
int []numbers = new int[count];
if(count>0) {
for(int i = 0; i < count; i++)
{
numbers[i] = in.nextInt();
sum = sum + numbers[i];
}
}
double average = sum/count;
System.out.print(average);
for(int j=0 ; j<numbers.length ; j++)
{
if(numbers[j]>average)
{
System.out.print(numbers[j]);
}
}
}
}
输出结果a[0]=b[0]
与 int i = j;(i与j占用两个独立的地址)不同, []a与[]b均为new出来数组的管理者,所以b[0]重新赋值两个a[0,b[0]均发生变化。
输出结果True,两个数组每个位置对应元素相同。
投票游戏:按-1结束,统计0-9输入同一数字的次数:
package array;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int x = in.nextInt();
int []numbers = new int[10];
while(x!=-1)
{
if(x>=0&&x<=9) {
numbers[x]++;
}
x = in.nextInt();
}
for(int i = 0; i < numbers.length ; i++)
{
System.out.println(i+":"+ numbers[i]+"次");
}
}
}
判断数字是否在数组中:
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
int []numbers = {3,4,2,8,9,1};
Scanner in = new Scanner(System.in); 如果不使用布尔型,要把初值设为-1
int k = in.nextInt();
boolean isPrime = false;
for( int x:numbers) //特有的for-each循环--单独遍历数组中的元素取出,但不能将数组中的元素赋值,修改
{
if(k == x) {
isPrime = true;
break;
}
}
if(isPrime) //这个条件代表布尔型是true的意思
{
System.out.print("在其中");
}
else
{
System.out.print("不在其中");
}
}
}
判断一个数是否是素数更快的数学方法:
构造前1-100之内素数表:(思路:素数的倍数取反,输出取正的结果)
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
boolean []isprime= new boolean[100];
for(int i = 2 ; i < isprime.length ; i++)
{
isprime[i] = true;
}
for(int i = 2 ; i < isprime.length ; i++)
{
if(isprime[i])
{
for(int k = 2;i*k<isprime.length;k++ )
{
isprime[i*k] = false;
}
}
}
for(int i = 2 ; i < isprime.length ; i++)
{
if(isprime[i])
{
System.out.println(i);
}
}
}
}
构造前50个素数:(思路:判断是否能被已知的且小于x的素数整除)
import java.util.Scanner;
public class Var {
public static void main(String[] args) {
// TODO Auto-generated method stub
int []numbers = new int[50];
numbers[0] = 2;
int cnt = 1;
MAIN_LOOP:
for(int x = 3;cnt<numbers.length;x++)
{
for(int loc = 0;loc<cnt;loc++)
{
if(x % numbers[loc] == 0 )
{
continue MAIN_LOOP;
}
}
numbers[cnt++] = x; //++号在cnt后面,等cnt使用完以后再加1。将x复制给第cnt个元素,赋值操作以后cnt++
}
for(int k:numbers)
{
System.out.print(k+" ");
}
System.out.println();
}
}
字符:
char c = (char)(‘a’-‘A’+‘A’); //输出c为a
System.out.println(‘汉’>‘A’) //输出结果为true,汉字比所有英文字母要大
System.out.println(Character.tolowerCase(‘I’)); //将大写字母转换成小写字母
character.isDigit(‘1’) //判断是不是数字
Interger.MAX_VALUE 2^31-1 —32bit----整型4个字节
Math.round() //做四舍五入
Math.random() //生成一个0-1之间的随机数【0-1)
Math.pow(2,3.2) //表示2的3.2次方
字符串变量: String s = new String(“a string”); //字符串变量是字符串的管理者而不是所有者
System.out.println(“abc”+12+24); //输出abc1224, 因为从左至右加号会先将12变为字符串形式,再+24
s=in.next() //如果用空格分隔每一个单词(a string),只能都读进来一个单词(a)
System.out.println(s.equals(“a”)); //判断字符串是否相等必须用equals不能用 == ,==是判断是否指向同一位置
字符串操作:
String s = “Hello”;
s.lengeh(); --> 这里的 .length() 是一个操作
s.charAt(0) //取出第0个字符是H
s.substring(2,4) //输出ll ,取出的是从第二个到第四个之前的部分字符串
int loc = s.indexOf(‘l’) //取出的第一个 l 的位置
System.println(s.indexOf(‘l’,loc+1)) //取出的第二个 l 的位置
函数形式判断是不是素数: //能否被小于他的数整除
import java.util.Scanner;
import java.util.Scanner;
public class Var {
public static boolean isPrime(int j)
{
boolean isPrime = true;
for(int i=2 ; i<j ; i++)
{
if(j%i == 0)
{
isPrime = false;
System.out.print("不是素数");
break;
}
}
return(isPrime);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int amount = in.nextInt();
if(isPrime(amount))
{
System.out.print("这是素数");
}
}
}
只能传值给函数,不能改变主函数的变量
二 面向对象程序设计 --java
1.用类制造对象
封装:把数据和对数据所有的操作放在一起
2.定义类:
package VendingMachine;
public class VendingMachine {
int price = 80;
int balance;
int total;
void showPrompt()
{
System.out.print(“请投入货币”);
}
void insertMoney(int amount)
{
balance = balance + amount;
}
void showBalance()
{
System.out.print(“余额:”+balance);
}
void getFood()
{
if( balance > price )
{
balance = balance - price;
total = total + price;
System.out.print("找零:"+balance);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
VendingMachine vm = new VendingMachine();
vm.showPrompt();
vm.insertMoney(100);
vm.showBalance();
vm.getFood();
}
}
成员函数:
public class VendingMachine {
int price = 80;
int balance;
int total;
void showPrice(int price)
{
this.price = price ; // 这里的this可以直接指向上面赋值80的price,而不加this只能指向离他最近的
} 传入函数括号内的price
在一个成员函数内部调用自己其他成员函数可以不加this
关于初始化:java会给成员变量一个默认的零值
构造函数:
public class VendingMachine {
int price = 80;
int balance = f();
int total;
void showPrompt()
{
System.out.print(“请投入货币”);
}
int f()
{
return 10;
}
VendingMachine() (1) //friendly位于同一个包的类可以访问
{
total = 0; //构造函数,不能返回任何值
}
VendingMachine(int price) //重载时访问 (2)
{
this(); //在构造函数里调用其他构造函数,只能在构造函数里出现,且只能使用一次
this.price = price;
}
void insertMoney(int amount)
{
balance = balance + amount;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
VendingMachine vm = new VendingMachine(); //走到这步后运行到(1)处
VendingMachine vm = new VendingMachine(100); //走到这步后运行到(2)处 重载
vm.showPrompt();
vm.insertMoney(100);
vm.showBalance();
vm.getFood();
}
对象的交互: 时钟*
package clock;
public class Dispaly {
private int value = 0;
private int limit = 0;
public Dispaly(int limit)
{
this.limit = limit;
}
public void increase()
{
value++;
if(value == limit)
{
value = 0;
}
}
int getValue()
{
return(value);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Dispaly d1 = new Dispaly(24);
for(;😉
{
d1.increase();
System.out.println(d1.getValue());
}
}
}
package clock; //Clock完成时钟与分钟的交互
public class Clock {
private Dispaly hour = new Dispaly(24); //private是私有的,只有在自己的类里面才能访问
private Dispaly minute = new Dispaly(60);
public void start()
{
while(true) {
minute.increase();
if(minute.getValue() == 0)
{
hour.increase();
}
System.out.printf("%02d:%02d\n",hour.getValue(),minute.getValue());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Clock c = new Clock();
c.start();
}
}
一个public类必须在自己的文件里面,一个文件只能有一个public类
java里面每一个点代表一级目录,包可以包含一个更深的包
类变量
package clock;
public class Dispaly {
private int value = 0;
private int limit = 0;
private static int step = 1;
public Dispaly(int limit)
{
this.limit = limit;
}
public void increase()
{
value++;
if(value == limit)
{
value = 0;
}
}
int getValue()
{
return(value);
}
public static void f()
{
错误示范:value++; //不可行的,static里不可以直接访问一个non-static的变量
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Dispaly d1 = new Dispaly(24);
f(); //static作为一个类函数,可以直接由另一个static函数访问
d1.f(); //也可由一个对象去访问
d1.step = 2; //此时 d1,d2的step均为2
Display d2 = new Display(12);
Display.step = 3;
System.out.println(Display.step); //static作为一个类变量,只有类变量可以直接通过类访问
System.out.println(d1.step); //三条语句都输出3,可在static函数里利用调用static变量
System.out.println(d2.step);
for(;;)
{
d1.increase();
System.out.println(d1.getValue());
}
}
}
容器
实现一个日记本
日记本的功能:
根据功能相应的接口设计:
package coumn;
import java.util.ArrayList; //ArrayList容量是无限的
public class Coumn {
private ArrayList notes = new ArrayList ();
public void add(String s)
{
notes.add(s);
}
public void add(String s,int location)
{
notes.add(location,s); //将String s插入loction这个位置
}
public int getSize()
{
return notes.size() ; //返回容器的大小
}
public String getNote(int index)
{
return notes.get(index); //输入的index(在容器中的位置),返回位置上的String
}
public void removeNote(int index)
{
notes.remove(index); //remove方法会把刚刚删掉的返回回来,如果index越界则抛出异常
}
public String[] list()
{
return new String[10];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Coumn c1 = new Coumn();
c1.add(“first”);
c1.add(“second”);
c1.add(“third”,1);
System.out.println(c1.getNote(0));
System.out.println(c1.getNote(1));
}
}
日记本成品
package coumn;
import java.util.ArrayList;
public class Coumn {
private ArrayList notes = new ArrayList ();
public void add(String s)
{
notes.add(s);
}
public void add(String s,int location)
{
notes.add(location,s);
}
public int getSize()
{
return notes.size() ;
}
public String getNote(int index)
{
return notes.get(index);
}
public void removeNote(int index)
{
notes.remove(index);
}
public String[] list()
{
String []a = new String[notes.size()]; //string数组的长度是容器的长度
//for(int i=0;i<notes.size();i++)
//{
//a[i] = notes.get(i);
//}
notes.toArray(a); //避免使用循环,直接将notes中每个元素放入数组a;
return a;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Coumn c1 = new Coumn();
c1.add(“first”);
c1.add(“second”);
c1.add(“third”,1);
System.out.println(c1.getNote(0));
System.out.println(c1.getNote(1));
System.out.println(c1.getNote(2));
System.out.println(c1.getSize());
String []b = c1.list(); //直接调用c1的list方法
for(String s:b) //使用for-each循环取出数组b中的元素
{
System.out.println(s);
}
}
}
对象数组
对象数组每一个元素都是对象的管理者,而非对象本身。如果对象数组没有给予一个元素创建出来的对象,则指向null
String数组就是对象数组,因为String变量本身就是对象需要new出来的,而普通数组int则不同
,整型变量不需要new
package coumn;
import java.util.ArrayList;
class Value //新构造一个Value类
{
private int i ;
public void set(int i)
{
this.i=i;
}
public int get()
{
return i;
}
public String toString()
{
return ;
}
}
public class Coumn {
private ArrayList notes = new ArrayList ();
public void add(String s)
{
notes.add(s);
}
public void add(String s,int location)
{
notes.add(location,s);
}
public int getSize()
{
return notes.size() ;
}
public String getNote(int index)
{
return notes.get(index);
}
public void removeNote(int index)
{
notes.remove(index);
}
public String[] list()
{
String []a = new String[notes.size()];
//for(int i=0;i<notes.size();i++)
//{
//a[i] = notes.get(i);
//}
notes.toArray(a);
return a;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Coumn c1 = new Coumn();
c1.add(“first”);
c1.add(“second”);
c1.add(“third”,1);
System.out.println(c1.getNote(0));
System.out.println(c1.getNote(1));
System.out.println(c1.getNote(2));
System.out.println(c1.getSize());
String []b = c1.list();
Value []v1 = new Value[10]; //构造一个Value类的对象数组
for(int i = 0; i < 10 ;i++)
{
v1[i] = new Value(); //对象数组内每一个元素都需要一个管理者
v1[i].set(i); //将数组内每一个值传入i
}
for(Value a:v1) //这里的for-each循环是v1给a赋值的关系,a可以直接使用v1中的方法
{
System.out.println(a.get());
}
ArrayList b = new ArrayList();
b.add(“first”);
b.add(“second”);
for(String f:b)
{
System.out.println(f); //容器ArrayList也可以使用for-each循环
}
for(String s:b)
{
System.out.println(s);
}
}
}
package coumn;
import java.util.ArrayList;
import java.util.HashSet;
class Value
{
private int i ;
public void set(int i)
{
this.i=i;
}
public int get()
{
return i;
}
public String toString()
//ArrayList<>与HashSet共同包含的功能都有String toString函数,此函数println 对象 ,会主动输出 i
//而新构造的对象函数本身内部没有封装过string tostring,需要自己构造
{
return(""+i);
}
}
public class Coumn {
private ArrayList notes = new ArrayList ();
public void add(String s)
{
notes.add(s);
}
public void add(String s,int location)
{
notes.add(location,s);
}
public int getSize()
{
return notes.size() ;
}
public String getNote(int index)
{
return notes.get(index);
}
public void removeNote(int index)
{
notes.remove(index);
}
public String[] list()
{
String []a = new String[notes.size()];
//for(int i=0;i<notes.size();i++)
//{
//a[i] = notes.get(i);
//}
notes.toArray(a);
return a;
}
HashSet集合
public static void main(String[] args) {
// TODO Auto-generated method stub
Value v2 = new Value();
v2.set(12);
System.out.println(v2);
HashSet s = new HashSet(); //HashSet代表集合
s.add(“first”);
s.add(“second”);
s.add(“third”);
System.out.println(s);
//输出 【first,second】 ,因为是集合,同理ArrayList可以以同样输出对象形式输出方括号。
System.out.println("…");
Value []v1 = new Value[10];
for(int i = 0; i < 10 ;i++)
{
v1[i] = new Value();
v1[i].set(i);
}
// for(Value a:v1)
// {
// System.out.println(a.get());
// }
//
}
}
Hash表
将金额对应得英文单词存在哈希表里,输入一个数字得到一个英文字符
package hash;
import java.util.HashMap;
import java.util.Scanner;
public class Coin {
private HashMap<Integer,String> coinnames= new HashMap<Integer,String>(); //哈希表
public Coin()
{
coinnames.put(1,“penny”);
coinnames.put(2,“dime”);
coinnames.put(5,“quarter”);
coinnames.put(10,“half-dolar”);
coinnames.put(10,“dolar”);
System.out.println(coinnames.keySet().size()); //输出哈希表里面元素的集合大小为四
System.out.println(coinnames);
//输出哈希表里面元素的集合,只有四个 “penny”, “dime”,“quarter”,“dolar”
输出 {1=penny, 2=dime, 5=quarter, 10=dolar} 四个键值对
}
for(int k : coinnames.keySet())
//遍历ArrayList与遍历HashSet都只需要直接for-each在输出即可。
//遍历哈希表则不同:需要先利用表得集合方法将(键值对中的键)赋值给K,再使用哈希表的get方法获取元素。
{
String z = coinnames.get(k);
System.out.println(z);
}
public String get(int amount)
{
if(coinnames.containsKey(amount)) //条件如果元素存在,则返回单词。
{
return coinnames.get(amount);
}
else
{
return “NOT FOUND”;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner c = new Scanner(System.in);
int amount = c.nextInt();
Coin c1 = new Coin();
System.out.println(c1.get(amount));
}
}
继承
实现一个可以装入DVD与CD的数据库
Database
package domb;
import java.util.ArrayList;
public class Database {
//private ArrayList CDlist= new ArrayList();
//private ArrayListDVDlist= new ArrayList();
private ArrayListItemlist= new ArrayList();
// public void add(CD cd)
// {
// CDlist.add(cd);
// }
// public void add(DVD dvd)
// {
// DVDlist.add(dvd);
// }
public void add(Item item)
{
Itemlist.add(item);
}
public void list()
{
for(Item item : Itemlist)
{
item.print();
}
// for(CD cd : CDlist)
// {
// cd.print();
// }
// for(DVD dvd : DVDlist)
// {
// dvd.print();
// }
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Database db = new Database();
db.add(new CD(“panama”, “jack”, 6, 6, “IGNB”));
db.add(new CD(“banama”, “back”, 7, 6, “IGNB”));
db.add(new DVD(“ganama”, “back”, 8,“IGNB”));
db.list();
}
}
CD
package domb;
public class CD extends Item{
private String artist;
private int numofTracks;
// private int playingTime;
// private boolean gotIt = false;
// private String comment;
public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
super(title, playingTime, false, comment); //super会自动调用父类的构造器,传入super中的参数要与被调用的父类的构造器中的参数相对应
this.artist = artist;
this.numofTracks = numofTracks;
// this.playingTime = playingTime;
// this.comment = comment;
}
public void print()
{
System.out.print(“CD:”);
super.print();
System.out.print(artist);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
DVD
package domb;
public class DVD extends Item {
// private String title;
private String director;
// private int playingTime;
// private boolean gotIt = false;
// private String comment;
public DVD(String title, String director, int playingTime, String comment) {
super(title,playingTime,false,comment); //若super中没有传入参数(不管有没有super),都会调用父类中一个没有形参的构造器(类似于重载)
//super只能调用一次且只能在第一行
// this.title = title; //如果子类与父类有完全相同的变量,则父类变量会被隐藏起来
this.director = director;
// this.playingTime = playingTime;
// this.comment = comment;
}
public void print()
{
System.out.print(“DVD:”);
super.print();
//这里如果要调用父类中的print要使用super.print(),不可以直接使用 print();因为会优先最 近的调用
父类也称为超类
System.out.print(director);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Item Item是DVD与CD的父类
package domb;
public class Item {
private String title; //父类中的private,子类不能访问
private int playingTime;
private boolean gotIt = false;
private String comment;
public void print()
{
System.out.println(title+"😊;
}
public Item() {
super();
}
public Item(String title, int playingTime, boolean gotIt, String comment) {
super();
this.title = title;
this.playingTime = playingTime;
this.gotIt = gotIt;
this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
多态及向上造型
Item相当于一个多态变量,而add(new cd(,,))发生了向上造型
上图:String s = “hello”; //"hello"并没有被bye覆盖,而是s与hello之间断开,与bye进行连接
s = “bye”
造型
package domb;
public class Item {
private String title; //父类中的private,子类不能访问
private int playingTime;
private boolean gotIt = false;
private String comment;
public void print()
{
System.out.println(title+"😊;
}
public Item() {
super();
}
public Item(String title, int playingTime, boolean gotIt, String comment) {
super();
this.title = title;
this.playingTime = playingTime;
this.gotIt = gotIt;
this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CD cd = new CD("hello", "zhou", 6, 7, "yes");
Item item = new Item("six", 6, false, "yesmodle");
item = cd; //cd可以赋值给item(作为一个父类),但是不能将item赋值给cd,相当于向上造型 item = (Item)cd;
CD cc = (CD)item; // 如果item里面已经装着CD类型了,但是仍不能将item交给一个CD的变量
} //所以需要强制将item造型成一个CD变量(与类型转换不同,只是把item当作一个CD变量,并不会改变item的类)
//如果没有 item = cd; ,强制造型后会抛出异常,必须在item里面装了CD的条件下才可以
}
假设现有4个类:Person、Teacher、Student和PhDStudent。Teacher 和Student都是Person的子类,PhDStudent是Student的子类。以下的赋值语句哪些是合法的,为什么?
Person p1 = new Student();
Person p2 = new PhDStudent();
PhDStudent phd1 = new Student();
Teacher t1 = new Person();
Student s1 = new PhDStudent();
s1 = p1;
s1 = p2;
P1 = s1;
t1 = s1;
s1 = phd1;
Phd1 = s1;
合法的有:
Person p1 = new Student(); 子类对象赋值给父类变量
Person p2 = new PhDStudent(); 子类对象赋值给父类变量
Student s1 = new PhDStudent(); 子类对象赋值给父类变量
p1 = s1; 子类对象赋值给父类变量
不合法的有:
PhDStudent phd1 = new Student(); 父类对象不能直接赋值给子类变量
Teacher t1 = new Person(); 父类对象不能直接赋值给子类变量
s1 = p1; 父类对象不能直接赋值给子类变量
s1 = p2; 父类对象不能直接赋值给子类变量
t1 = s1; t1未被成功创建,且t1与s1的类型没有直接关系
s1 = phd1; phd1未被成功创建,若成功创建则合法
Phd1 = s1; phd1未被成功创建,且父类对象不能直接赋值给子类变量
多态:
for(Item item:Itemlist)
{
Item.print(); 声明类型:Item
System.out.println(); 动态类型:DVD CD Item.print(); 调用实际的动态类型
}
draw的函数有多个,这里shape调用会自动选择
类型系统----Object
package domb;
public class CD extends Item{
private String artist;
private int numofTracks;
// private int playingTime;
// private boolean gotIt = false;
// private String comment;
public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
super(title, playingTime, false, comment); //super会自动调用父类的构造器,传入super中的参数要与被调用的父类的构造器中的参数相对应
this.artist = artist;
this.numofTracks = numofTracks;
// this.playingTime = playingTime;
// this.comment = comment;
}
public void print()
{
System.out.print(“CD:”);
//super.print();
System.out.print(artist);
}
@Override
public String toString() { //构造String toString函数,source-Generate toString创建String toString()
return "CD [artist=" + artist + ", numofTracks=" + numofTracks + ", toString()=" + super.toString() + "]";
} //arraylist与hashset都封装了String toString函数,CD中没有,需要自己改写
public static void main(String[] args) {
// TODO Auto-generated method stub
CD cd = new CD("panama", "jack", 6, 6, "IGNB");
CD cd1 = new CD("panama", "jack", 6, 6, "IGNB");
String s = "aa"+cd1;
System.out.print(s); //将对象cd1以string(String toString)输出,如果不改写object输出的是地址
System.out.println(cd.equals(cd1)); //equals判断cd与cd1是否为同一管理者
} //string中的equals方法是将 object中的equals方法进行的改写,而这里cd中的equals方法与string中的equals方法耦合
@Override
public boolean equals(Object obj) { //source-override methods自动创建equals函数
CD cc = (CD)obj; //cd1作为object类传入,将obj向下造型存入cc中
return artist.equals(cc.artist); //equals判断cd与cd1是否为同一管理者,其中调用artist字符串类所带有的equals方法 进行比较
}
}
如果要在VideoGame基础上增加一个BoardGame,可以选择一个更深的继承
城堡游戏–消除代码复制
package Ga;
import java.util.*;
public class Castle {
private Room currentRoom;
public Castle() {
createRooms();
}
public void createRooms() {
Room outside,lobby,pub,study,bedroom;
//创造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口
outside.setExits(null,lobby,study,pub);
lobby.setExits(null,null,null,outside);
pub.setExits(outside,bedroom,null,null);
bedroom.setExits(null,null,null,study);
currentRoom = outside; //从城堡门外开始
}
private void printWelcome()
{
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入'help'");
System.out.println();
System.out.println("现在你在:" + currentRoom);
System.out.println("欢迎来到城堡");
prompt();
}
// 以下为用户命令
private void printHelp()
{
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
private void goRoom(String direction){
Room nextRoom = null;
if(direction.equals("north")){
nextRoom = currentRoom.northExit;
}
if(direction.equals("east")){
nextRoom = currentRoom.eastExit;
}
if(direction.equals("south")){
nextRoom = currentRoom.southExit;
}
if(direction.equals("west")){
nextRoom = currentRoom.westExit;
}
if(nextRoom == null){
System.out.println("那里没有门!");
}
else{
currentRoom = nextRoom;
prompt();
}
}
public void prompt() {
System.out.println("你在"+ currentRoom);
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("norh");
if(currentRoom.eastExit != null)
System.out.println("east");
if(currentRoom.southExit != null)
System.out.println("south");
if(currentRoom.westExit != null)
System.out.println("west");
System.out.println();
} //将此部分重复的代码封装成一个函数消除代码复制
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Castle game = new Castle();
game.printWelcome();
while (true){
String line = in.nextLine();
String[] words = line.split(" ");
if ( words[0].equals("help")){
game.printHelp();
}else if ( words[0].equals("go")){
game.goRoom(words[1]);
}else if ( words[0].equals("bye")){
break;
}
}
System.out.println("感谢您的光临。再见!");
in.close();
}
}
package Ga;
public class Room {
public String description;
public Room northExit;
public Room southExit;
public Room eastExit;
public Room westExit;
public Room(String description)
{
this.description = description;
}
public void setExits(Room north,Room east,Room south,Room west)
{
if(north != null)
northExit = north;
if(east != null)
eastExit = east;
if(south != null)
southExit = east;
if(west != null)
westExit = west;
}
@Override
public String toString()
{
return description;
}
public void southExit(Object object, Room lobby, Room study, Room pub) {
// TODO Auto-generated method stub
}
}
城堡游戏–耦合和聚合
要评判某些设计比其他的设计优秀,就得定义一些在类的设计中重要的术语,以用来讨论 设计的优劣。对于类的设计来说,有两个核心术语:耦合和聚合。 耦合这个词指的是类和类之间的联系。之前的章节中提到过,程序设计的目标是一系列通 过定义明确的接口通信来协同工作的类。耦合度反映了这些类联系的紧密度。我们努力要获得 低的耦合度,或者叫作松耦合(loose coupling)。
耦合度决定修改应用程序的容易程度。在一个紧耦合的结构中,对一个类的修改也会导致 对其他一些类的修改。这是要努力避免的,否则,一点小小的改变就可能使整个应用程序发生 改变。另外,要想找到所有需要修改的地方,并一一加以修改,却是一件既困难又费时的事情。 另一方面,在一个松耦合的系统中,常常可以修改一个类,但同时不会修改其他类,而且 整个程序还可以正常运作。
本周会讨论紧耦合和松耦合的例子。 聚合与程序中一个单独的单元所承担的任务的数量和种类相对应有关,它是针对类或方法 这样大小的程序单元而言的理想情况下,一个代码单元应该负责一个聚合的任务(也就是说,一个任务可以被看作是 一个逻辑单元)。一个方法应该实现一个逻辑操作,而一个类应该代表一定类型的实体。聚合 理论背后的要点是重用:如果一个方法或类是只负责一件定义明确的事情,那么就很有可能在 另外不同的上下文环境中使用。遵循这个理论的一个额外的好处是,当程序某部分的代码需要 改变时,在某个代码单元中很可能会找到所有需要改变的相关代码段。
城堡游戏–封装
package Ga;
import java.util.*;
public class Castle {
private Room currentRoom;
public Castle() {
createRooms();
}
public void createRooms() {
Room outside,lobby,pub,study,bedroom;
//创造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口
outside.setExits(null,lobby,study,pub);
lobby.setExits(null,null,null,outside);
pub.setExits(outside,bedroom,null,null);
bedroom.setExits(null,null,null,study);
currentRoom = outside; //从城堡门外开始
}
private void printWelcome()
{
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入'help'");
System.out.println();
System.out.println("现在你在:" + currentRoom);
System.out.println("欢迎来到城堡");
prompt();
}
// 以下为用户命令
private void printHelp()
{
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
private void goRoom(String direction){
Room nextRoom = currentRoom.getExit(direction);
//解耦合,输出下一个Room
if(nextRoom == null){
System.out.println("那里没有门!");
}
else{
currentRoom = nextRoom;
prompt();
}
}
public void prompt() {
System.out.println("你在"+ currentRoom);
System.out.println("出口有:");
System.out.println(currentRoom.getExitDes()); //解耦合输出当前的出口
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Castle game = new Castle();
game.printWelcome();
while (true){
String line = in.nextLine();
String[] words = line.split(" ");
if ( words[0].equals("help")){
game.printHelp();
}else if ( words[0].equals("go")){
game.goRoom(words[1]);
}else if ( words[0].equals("bye")){
break;
}
}
System.out.println("感谢您的光临。再见!");
in.close();
}
}
package Ga;
public class Room {
public String description;
private Room northExit;
private Room southExit;
private Room eastExit;
private Room westExit;
public Room(String description)
{
this.description = description;
}
public void setExits(Room north,Room east,Room south,Room west)
{
if(north != null)
northExit = north;
if(east != null)
eastExit = east;
if(south != null)
southExit = east;
if(west != null)
westExit = west;
}
@Override
public String toString()
{
return description;
}
public String getExitDes (){ //解耦合
StringBuffer sb = new StringBuffer(); //相比于str+=更利于空间的利用
if(northExit != null)
sb.append(“north”);
if(eastExit != null)
sb.append(“east”);
if(southExit != null)
sb.append(“south”);
if(westExit != null)
sb.append(“west”);
return sb.toString(); //输出结构字符
}
public Room getExit(String direction)
{
Room ret = null;
if(direction.equals(“north”)){
ret = northExit;
}
if(direction.equals(“east”)){
ret = eastExit;
}
if(direction.equals(“south”)){
ret = southExit;
}
if(direction.equals(“west”)){
ret = westExit;
}
return ret; //输出下一个房间
}
//public void southExit(Object object, Room lobby, Room study, Room pub) {
// TODO Auto-generated method stub
//}
}
可扩展性
package Ga;
import java.util.*;
public class Castle {
private Room currentRoom;
public Castle() {
createRooms();
}
public void createRooms() {
Room outside,lobby,pub,study,bedroom;
//创造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口 //增强可扩展性运用哈希表添加元素
outside.setExits("south", lobby);
outside.setExits("east", study);
outside.setExits("west", pub);
lobby.setExits("west",outside);
pub.setExits("north", outside);
pub.setExits("bedroom", bedroom);
bedroom.setExits("west",study);
pub.setExits("up", lobby);
lobby.setExits("down",pub);
currentRoom = outside; //从城堡门外开始
}
private void printWelcome()
{
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入'help'");
System.out.println();
System.out.println("现在你在:" + currentRoom);
System.out.println("欢迎来到城堡");
prompt();
}
// 以下为用户命令
private void printHelp()
{
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
private void goRoom(String direction){
Room nextRoom = currentRoom.getExit(direction);
if(nextRoom == null){
System.out.println("那里没有门!");
}
else{
currentRoom = nextRoom;
prompt();
}
}
public void prompt() {
System.out.println("你在"+ currentRoom);
System.out.println("出口有:");
System.out.println(currentRoom.getExitDes());
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Castle game = new Castle();
game.printWelcome();
while (true){
String line = in.nextLine();
String[] words = line.split(" ");
if ( words[0].equals("help")){
game.printHelp();
}else if ( words[0].equals("go")){
game.goRoom(words[1]);
}else if ( words[0].equals("bye")){
break;
}
}
System.out.println("感谢您的光临。再见!");
in.close();
}
}
package Ga;
import java.util.HashMap;
public class Room {
public String description;
private Room northExit;
private Room southExit;
private Room eastExit;
private Room westExit;
private HashMap<String,Room> exists = new HashMap<String,Room>();
public Room(String description)
{
this.description = description;
}
public void setExits(String dir,Room room) 增强可扩展性,构造哈希表
{
exists.put(dir,room);
}
// public void setExits(Room north,Room east,Room south,Room west)
// {
// if(north != null)
// northExit = north;
// if(east != null)
// eastExit = east;
// if(south != null)
// southExit = east;
// if(west != null)
// westExit = west;
// }
@Override
public String toString()
{
return description;
}
public String getExitDes (){
StringBuffer sb = new StringBuffer();
for(String dir: exists.keySet() )
{
sb.append(dir); //增强可扩展性,添加房间可走的 方向
}
// if(northExit != null)
// sb.append(“norh”);
// if(eastExit != null)
// sb.append(“east”);
// if(southExit != null)
// sb.append(“south”);
// if(westExit != null)
// sb.append(“west”);
return sb.toString();
}
public Room getExit(String dir)
{
Room ret = null;
// if(direction.equals(“north”)){
// ret = northExit;
// }
// if(direction.equals(“east”)){
// ret = eastExit;
// }
// if(direction.equals(“south”)){
// ret = southExit;
// }
// if(direction.equals(“west”)){
// ret = westExit;
// } //增强可扩展性,获得该方向上房间
return exists.get(dir);
}
//public void southExit(Object object, Room lobby, Room study, Room pub) {
// TODO Auto-generated method stub
//}
}
框架加数据
package Ga;
import java.util.*;
import java.util.HashMap;
public class Castle {
private Room currentRoom;
private HashMap<String,Handler> handlers = new HashMap<String,Handler>(); //将用户的命令转化为哈希表中的String,将接到命令以后的操作转化为哈希表中的Handler类中的函数
public Castle() {
createRooms();
handlers.put(“bye”, new HandlerBye(this)); //由于HandlerBye,HandlerHelp,HandlerGo中均有Castle属性,所以要在括号里加入this
handlers.put(“help”, new HandlerHelp(this));
handlers.put(“go”, new HandlerGo(this));
}
public void play(){
Scanner in = new Scanner(System.in);
while(true) {
String line = in.nextLine();
String[] words = line.split(" ");
Handler handler = handlers.get(words[0]); //取哈希表中键String为words[0]时的数值
String value = “”;
if(words.length>1)
{
value = words[1];
}
if(handler!=null) {
handler.docmd(value);
if ( handler.isBye()){
break;
}
}
}
};
public void createRooms() {
Room outside,lobby,pub,study,bedroom;
//创造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口
outside.setExits("south", lobby);
outside.setExits("east", study);
outside.setExits("west", pub);
lobby.setExits("west",outside);
pub.setExits("north", outside);
pub.setExits("bedroom", bedroom);
bedroom.setExits("west",study);
pub.setExits("up", lobby);
lobby.setExits("down",pub);
currentRoom = outside; //从城堡门外开始
}
private void printWelcome()
{
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入'help'");
System.out.println();
System.out.println("现在你在:" + currentRoom);
System.out.println("欢迎来到城堡");
prompt();
}
// 以下为用户命令
// private void printHelp()
// {
//
// }
public void goRoom(String direction){
Room nextRoom = currentRoom.getExit(direction);
if(nextRoom == null){
System.out.println("那里没有门!");
}
else{
currentRoom = nextRoom;
prompt();
}
}
public void prompt() {
System.out.println("你在"+ currentRoom);
System.out.println("出口有:");
System.out.println(currentRoom.getExitDes());
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
}
//System.out.println("感谢您的光临。再见!");
//in.close();
}
package Ga;
public class Handler { //所有Handler操作的父类
public void docmd(String k) {};
public boolean isBye() {return false;} ; //如果传入的值的键不是HandlerBye则返回false
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
package Ga;
public class HandlerBye extends Handler { // HandlerBye为Handler的子类执行用户输入bye时的操作
@override
public boolean isBye() {return true;} ; //继承了父类返回true
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
package Ga;
public class HandlerGo extends Handler{
public HandlerGo(Castle castle) {
super(castle);
}
@override
//public void docmd(String word)
//{
//Castle.goRoom(word);
//};
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
package Ga;
public class HandlerHelp extends Handler{
public HandlerHelp(Castle castle) {
super(castle);
}
@override
public void docmd(String k)
{
System.out.println(“迷路了吗?你可以做的命令有:go bye help”);
System.out.println(“如:\tgo east”);
};
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
隐形耦合
现在的代码,如果增加新的命令,那么help所输出的内容就需要做变化,而help的输出内容目前是硬编码的。如何修改代码能实现help的输出内容与help的输出函数无关,使得新的命令加入的时候,help能自动输出新的内容
1、在Game类中增加一个接口,返回所有的指令
public Set getAllCmds(){
return this.handlers.keySet();
}
2、修改HandlerHelp中的输出代码
@Override
public void doCmd(String word) {
System.out.println("迷路了吗?你可以做的命令有:");
for(String k : this.game.getAllCmds()) {
System.out.print(k); //打印返回的KeySet中的键
System.out.print(" ");
}
System.out.println("如:\tgo east");
}
如何实现任意门?
如果想要实现任意门,即在某个房间,想要从某个出口出去,结果每次会走到不同的房间去。
如果要实现这样的任意门,整个程序的架构应该是怎样的?
如果任意门只是在这个房间的所有的门之间轮转,应该怎样实现?
如果任意门能在整个城堡的所有的门之间轮转,应该怎样实现?
实现任意门,就是要添加相应的命令(比如poll),即:
// Game.java
public Game() {
…
handlers.put(“poll”, new HandlerPoll(this));
createRooms();
}
为此,需要创建相应的Handler子类,并重写doCmd(String word)来实现具体功能:
// HandlerPoll.java
public void doCmd(String word) {
game.pollRoom();
}
和HandlerGo类似,此功能需要调用game的相应方法来完成,所以还要在Game类中添加这个方法。其具体实现方式有两种:
在Room类中实现轮转
// Game.java
public void pollRoom() {
currentRoom.pollExit();
}
// Room.java
public void pollExit() {
// 实现轮转
}
在Game类中实现轮转
// Game.java
public void pollRoom() {
Room[] exitss = currentRoom.getExits();
// 实现轮转
}
// Room.java
public void getExits() {
return exits.values().toArray(new Room[0]);
}
优先选择方法1,因为它的耦合更松。但如果要求任意门能在整个城堡的所有的门之间轮转,方法1就不适用了,此时就只能使用方法2。
抽象与接口
在第一周就有一个Shape类的例子。这个类有很多的子类,每个子类也都实现了父类的方法。实际上父类Shape只是一个抽象的概念而并没有实际的意义。如果请你画一个圆,你知道该怎么画;如果请你画一个矩形,你也知道该怎么画。但是如果我说:“请画一个形状,句号”。你该怎么画?同样,我们可以定义Circle类和Rectangle类的draw(),但是Shape类的draw()呢?
Shape类表达的是一种概念,一种共同属性的抽象集合,我们并不希望任何Shape类的对象会被创建出来。那么,我们就应该把这个Shape类定义为抽象的。我们用abstract关键字来定义抽象类。抽象类的作用仅仅是表达接口,而不是具体的实现细节。抽象类中可以存在抽象方法。抽象方法也是使用abstract关键字来修饰。抽象的方法是不完全的,它只是一个方法签名而完全没有方法体。
如果一个类有了一个抽象的方法,这个类就必须声明为抽象类。如果父类是抽象类,那么子类必须覆盖所有在父类中的抽象方法,否则子类也成为一个抽象类。一个抽象类可以没有任何抽象方法,所有的方法都有方法体,但是整个类是抽象的。设计这样的抽象类主要是为了防止制造它的对象出来。
package shapes;
import java.awt.Graphics;
public abstract class Shape {
public abstract void draw(Graphics g);
public abstract void move(Graphics g); //在父抽象类中添加一个抽象函数后在其子类中都会报错
}
package shapes;
import java.awt.Graphics;
public class Circle extends Shape {
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius)
{
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw(Graphics g) {
g.drawOval(x-radius, y-radius, radius*2, radius*2);
}
@Override
public void move(Graphics g) { //由于在父类中添加了一个抽象方法,所以子类必须要把父类中继承来的抽象方法覆盖掉
// TODO Auto-generated method stub
}
}
package shapes;
import java.awt.Graphics;
public class Triangle extends Shape {
private int[] x = new int[3];
private int[] y = new int[3];
public Triangle(int x1, int y1, int x2, int y2, int x3, int y3)
{
x[0] = x1; x[1] = x2; x[2] = x3;
y[0] = y1; y[1] = y2; y[2] = y3;
}
@Override
public void draw(Graphics g) {
g.drawPolygon(x, y, x.length);
}
@Override
public void move(Graphics g) { //由于在父类中添加了一个抽象方法,所以子类必须要把父类中继承来的抽象方法覆盖掉
// TODO Auto-generated method stub
}
}
如果shape为abstract类,则抽象得类无法实例化对象s,则s.draw无法实现。如果shape不为abstract,s.draw依然无法实现,因为draw函数没有函数体
数据与表现分离
Field只保存细胞的数据,cellMachine负责更新细胞的生存状态,view负责从field中取出细胞数据来paint
相比使用setAlive(boolean)函数,die()、reborn()两个函数其实显得更简单直接。
对于程序员来说,die()、reborn()的可读性更高,表达的意思明确,如老师所说,数据和表现分离,程序质量更好;
使用die()、reborn()函数,对于未来扩展程序功能来说,是保证cell与cellmashine的低耦合的良好选择。
1、降低Field和Cell的耦合度,分离二者的功能。对Cell内部的操作都交由CellMachine来完成,Field本身只负责管理Cell对象的位置,不会访问Cell内部的函数和变量。
2、便于维护和扩展。如果以后需要实现其他功能时也会用到Cell的邻居,不需要对Cell和Field做任何修改,只需要在CellMachine里修改就可以。
如果让Cell自己判断邻居情况,就需要Cell知道Field,会增加二者的耦合度;
判断属于业务逻辑的范畴,鉴于数据与表现分离的原则,Cell也不应该自己判断自己的邻居的情况来决定自己是否应该被die或reborn。
接口–狐狸与兔子
animal类
cell此时作为一个接口
//Fox extends Animal implements Cell 指FOX作为animal子类实现了Cell接口
package twenty.july.my_interface.animal;
import java.util.ArrayList;
import twenty.july.my_interface.field.Location;
public abstract class Animal {
private int ageLimit;
private int breedableAge;
private int age;
private boolean isAlive = true;
public Animal(int ageLimit, int breedableAge) {
this.ageLimit = ageLimit;
this.breedableAge = breedableAge;
}
protected int getAge() {
return age;
}
protected double getAgePercent() {
return (double) age / (double) ageLimit;
}
public abstract Animal breed();
public void grow() {
age++;
if (age >= ageLimit)
die();
}
public void die() {
isAlive = false;
}
public boolean isAlive() {
return isAlive;
}
public boolean isBreedable() {
return (age >= breedableAge);
}
public Location move(Location[] freeAdj) {
Location ret = null;
if (freeAdj.length > 0 && Math.random() < 0.02) {
ret = freeAdj[(int) (Math.random() * freeAdj.length)];
}
return ret;
}
@Override
public String toString() {
return “” + age + “:” + (isAlive ? “live” : “dead”);
}
public Animal feed(ArrayList neighbor) {
return null;
}
protected void longerLife(int inc) {
ageLimit += inc;
}
}
package twenty.july.my_interface.animal;
import java.awt.Graphics;
import java.awt.Color;
import java.util.ArrayList;
import twenty.july.my_interface.cell.Cell;
fox类
/**
- *Fox实现接口Cell,使Fox对象能间接传给Field
*/
public class Fox extends Animal implements Cell {
public Fox() {
super(20, 4);
}
@Override // 实现接口Cell中的draw()
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int) ((1 - getAgePercent()) * 255);
g.setColor(new Color(0, 0, 0, alpha));
g.fillRect(x, y, size, size);
}
@Override
public Animal breed() {
Animal ret = null;
if (isBreedable() && Math.random() < 0.05) {
ret = new Fox();
}
return ret;
}
@Override
public String toString() {
return (“Fox:” + super.toString());
}
@Override
public Animal feed(ArrayList neighbor) {
Animal ret = null;
if (Math.random() < 0.2) {
ret = neighbor.get((int) (Math.random() * neighbor.size()));
longerLife(2);
}
return ret;
}
}
rabbit类
package twenty.july.my_interface.animal;
import java.awt.Color;
import java.awt.Graphics;
import twenty.july.my_interface.cell.Cell;
public class Rabbit extends Animal implements Cell {
public Rabbit() {
super(10, 2); // *寿命&&生育年龄
}
@Override
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int) ((1 - getAgePercent()) * 255);
g.setColor(new Color(255, 0, 0, alpha));
g.fillRect(x, y, size, size);
}
@Override
public Animal breed() {
Animal ret = null;
if (isBreedable() && Math.random() < 0.12) {
ret = new Rabbit();
}
return ret;
}
@Override
public String toString() {
return “Rabbit” + super.toString();
}
}
cell类
package twenty.july.my_interface.cell;
import java.awt.Graphics;
public interface Cell {//注意这里不能写成interface class
/**
- *Cell是一个接口而非类(接口是一种完全抽象的抽象类)
- !这个接口就是为了实现Fox和Rabbit类new的对象能够传递给Field类
- Field类中指明需要的对象的类是Cell而Cell是作为中间承接者
- Fox和Rabbit类需要有implements Cell语句来实现接口
/
/* - !注意这里函数可以不用写函数前缀,只需要写返回值类型
- ?抽象类无函数主体,只需声明函数原型,实现抽象类/接口的类都必须Override所有抽象方法,否则此子类仍为抽象类
- ?abstract与final是冲突对立关系,抽象是用来被继承或重写的,final相反是不让继承/重写的
*/
void draw(Graphics g, int x, int y, int size);
}
Field类
package twenty.july.my_interface.field;
import java.util.ArrayList;
import twenty.july.my_interface.cell.Cell;
public class Field {
private int width;
private int height;
private Cell[][] field;// 声明有这么个数组变量,但未承接任何对象
private static final Location[] adjacent = {
new Location(-1, -1), new Location(-1, 0), new Location(-1, 1),
new Location(0, -1), new Location(0, 0), new Location(0, 1),
new Location(1, -1), new Location(1, 0),new Location(1, 1),
};
public Field(int width, int height) {
this.width = width;
this.height = height;
field = new Cell[height][width];
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Cell place(int row, int col, Cell o) {
// !这里的Cell o并非Cell类的对象,而是实现了Cell接口的对象(fox,rabbit)
field[row][col] = cell;
Cell ret = field[row][col];
return ret;
}
public Cell get(int row, int col) {
return field[row][col];
}
public Cell[] getNeighbor(int row, int col) {
ArrayList list = new ArrayList();
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
int r = row + i;
int c = col + j;
if (r > -1 && r < height && c > -1 && c < width && !(r == row && c == col)) {
list.add(field[r][c]);
}
}
}
return list.toArray(new Cell[list.size()]);
}
public Location[] getFreeNeighbor(int row, int col) {
ArrayList list = new ArrayList();
for (Location loc : adjacent) {
int r = row + loc.getRow();
int c = col + loc.getCol();
if (r > -1 && r < height && c > -1 && c < width && field[r][c] == null) {
list.add(new Location(r, c));
}
}
// !学着点
return list.toArray(new Location[list.size()]);
}
public boolean placeRandomAdj(int row, int col, Cell cell) {
boolean ret = false;
Location[] freeAdj = getFreeNeighbor(row, col);
if (freeAdj.length > 0) {
int idx = (int) (Math.random() * freeAdj.length);
field[freeAdj[idx].getRow()][freeAdj[idx].getCol()] = cell;
ret = true;
}
return ret;
}
public void clear() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
field[i][j] = null;
}
}
}
public void remove(Cell fed) {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (field[row][col] == fed) {
field[row][col] = null;
break;
}
}
}
}
public Cell remove(int row, int col) { // *函数重构
field[row][col] = null;
Cell ret = field[row][col];
return ret;
}
public void move(int row, int col, Location loc) {
field[loc.getRow()][loc.getCol()] = field[row][col];
remove(row, col);
}
}
location类
package twenty.july.my_interface.field;
public class Location {
private int row;
private int col;
public Location(int row, int col) {
this.row = row;
this.col = col;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
}
view类
package twenty.july.my_interface.field;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
import twenty.july.my_interface.cell.Cell;
public class View extends JPanel {
private static final long serialVersionUID = -2417015700213488315L;
private static final int GRID_SIZE = 16;
private Field theField;
// *构造函数
public View(Field field) {
theField = field;
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.GRAY);
for (int row = 0; row < theField.getHeight(); row++)
g.drawLine(0, row * GRID_SIZE, theField.getWidth() * GRID_SIZE, row * GRID_SIZE);
for ( int col = 0; col<theField.getWidth(); col++ )
g.drawLine(col * GRID_SIZE, 0, col * GRID_SIZE, theField.getHeight() * GRID_SIZE);
for (int row = 0; row < theField.getHeight(); row++) {
for (int col = 0; col < theField.getWidth(); col++) {
Cell cell = theField.get(row, col);
if (cell != null)
cell.draw(g, col * GRID_SIZE, row * GRID_SIZE, GRID_SIZE);
}
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(theField.getWidth() * GRID_SIZE + 1, theField.getHeight() * GRID_SIZE + 1);
}
}
fox与rabbit类
package twenty.july.my_interface.fox_and_rabbit;
import java.util.ArrayList;
import javax.swing.JFrame;
import twenty.july.my_interface.animal.;
import twenty.july.my_interface.cell.Cell;
import twenty.july.my_interface.field.;
public class FoxAndRabbit {
private Field theField;
private View theView;
public FoxAndRabbit(int size) {
theField = new Field(size, size);
for (int row = 0; row < theField.getHeight(); row++) {
for (int col = 0; col < theField.getWidth(); col++) {
double probability = Math.random();
if (probability < 0.05) {
theField.place(row, col, new Fox());
} else if (probability < 0.15) {
theField.place(row, col, new Rabbit());
}
}
}
theView = new View(theField);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setTitle(“Cells”);
frame.add(theView);
frame.pack();
frame.setVisible(true);
}
public void start(int steps) {
for (int i = 0; i < steps; i++) {
step();
theView.repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void step() {
for (int row = 0; row < theField.getHeight(); row++) {
for (int col = 0; col < theField.getWidth(); col++) {
Cell cell = (Cell) theField.get(row, col);
if (cell != null) {
Animal animal = (Animal) cell;
animal.grow();
if (animal.isAlive()) {
// *move
Location loc = animal.move(theField.getFreeNeighbor(row, col));
if (loc != null)
theField.move(row, col, loc);
// *eat
Cell[] neighbor = (Cell[]) theField.getNeighbor(row, col);
ArrayList listRabbit = new ArrayList();
for (Cell an : neighbor) {
if (an instanceof Rabbit) { // instanceof 判断是不是一个rabbit类
listRabbit.add((Rabbit) an);
}
}
if (!listRabbit.isEmpty()) {
Animal fed = animal.feed(listRabbit);
if (fed != null)
theField.remove((Cell) fed);
}
// *breed
Animal baby = animal.breed();
if (baby != null) {
theField.placeRandomAdj(row, col, (Cell) baby);
}
} else {
theField.remove(row, col);
}
}
}
}
}
public static void main(String[] args) {
FoxAndRabbit fnr = new FoxAndRabbit(50);
fnr.start(100);
}
}
不能使用animal.eat(theField),如果这么使用意味着cell知道了Field,原本是animal-Fox-rabbit是分离的,这样会使程序耦合性更紧,可扩展性变差,所以使用business-logic第三方业务逻辑程序去处理 fox得eat这个功能 。
1.Cell不知道Field:
优点:一方面,降低耦合度,保证程序的可扩展性;另一方面,遵从了数据和表现分离的原则,程序质量更佳。
缺点:Field知道Cell而Cell不知道Field的单向性,需要借助第三方平台完成业务逻辑,即进行额外的类型创建。
Cell知道Field:
优点:二者之间直接连通,不需要额外创建平台构建二者的联系。
缺点:二者的耦合度提高,关联性大,逻辑相对于不知道的情况下更复杂,不利于程序的扩展,程序的可读性也会下降,
2.要不要Animal的列表?
如果另外用一个ArrayList来表示所有的动物,每一步遍历这个列表而非整个Field,这样做是否更好?
提示:这样就需要每个Animal知道自己在Field里的位置
ArrayList不能完全取代Field,因为涉及到位置的操作难以高效地完成,比如Field很容易知道某行某列有没有动物,而ArrayList需要遍历整个列表。
还有个问题是遍历装着动物的容器时,对动物的操作又更新了容器,两者会有冲突,原来的代码就有这个bug:比如第1行第1列的兔子遍历时移到了第1行第2列,下个碰到的还是它……于是一轮遍历下来,有些动物会访问多次。一个解决办法是遍历容器的副本,这样每轮遍历前我们都要把Field复制一次;另外也可以让Field提供一个方法,扫描获得所有动物的列表,然后返回它来遍历。
3.要不要把数据和表现进一步分离?
现在Cell接口其实是承担了两个责任的。在Field看过来,它只认识Cell,它认为Cell是存放在其中的数据。而对于View来说,它看到的是Cell所具有的draw方法,从这个角度来说Cell表示了表现。
有没有必要两种分开。比如有一个Cell抽象类表示可以放进Field的东西,另一个Drawable接口表示可以被Vier画出来的东西
异常
1-5每一个步骤都可能会出现异常,而且前一步是下一步的基础
捕获每一步可能发生的异常并处理异常
有异常抛出如果所处是函数则下一步到该函数调用者,如果所处代码块不是函数或是try但不与catch匹配都退出到外层在进行判断是否是try是否是函数返回调用者
e.getMessage()代表使用捕获到的异常e的getMessage()方法获得到的 异常 的信息为10证(数组索引为10处超过边界)
直接println(e)输出10,main(报错的代码块是main)说明异常已经封装了String toString函数了
e.printStackTrace后台打印出报的异常的路径
在catch中对异常进行处理后,throw e;相当于再将异常抛出
class OpenException extends Throwable{} //构造新的异常时需要创建新的异常类,让其继承自Throwable变成可抛出的异常
class CloseException extends Throwable{} //所有的系统的异常都是继承自Exception的,而Throwable是继承自Exception的
public class ArrayIndex {
public static int open() {
return -1;
}
public static void readFile() throws OpenException,CloseException
{ //如果调用一个可能会抛出异常的函数则必须:
try { //1.在封装读入文件函数中抛出异常功能时要么在函数后声明throws OpenException,CloseException
//并在测试用例中在调用readFile时加入try-Catch块捕捉异常进行处理
//2.要么在readFile函数中的throw new OpenException();代码块的外部加入try-Catch块捕捉异常进行处理
if(open()==-1)
{
throw new OpenException();
}
}catch(OpenException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
readFile();
} catch (OpenException | CloseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (NullPointerException e)
{
e.printStackTrace();
}
}
}
这段代码前面 closeException继承自openException,openException继承自Exception,后面测试用例处会先被catch(closeException)捕获子类异常的代码捕捉到,就轮不到后面捕获父类openException的代码就终止了。
而如果将子类的catch放在父类的catch后面,则会优先被捕捉父类异常的代码捕捉,子类catch处报错.。。
catch(Exception e)能捕捉任何异常,如果前面的程序把catch(OpenException e)放在前面,catch(Exception e)放在后面,则程序不会报错,因为OpenException是Exception的子类。
【如果在main最后加入catch(Exception e)捕捉所有异常】在出现索引超出数组维度(运行时刻异常)后,程序还没有运行到openException就直接进入try-catch代码块,并报出运行时刻异常时的错误。
当异常遇上继承
class OpenException extends Exception{} //作为子类的成员函数不能增加比父类更多的异常
class CloseException extends OpenException{} //作为子类的构造函数可以增加比父类更多的异常
class NewException extends Exception{}
public class Exception2 {
public Exception2() throws OpenException{} //当父类的构造函数声明了异常时
public void f() throws OpenException{}
}
class Exception3 extends Exception2
{
public void f() throws OpenException{}
//public void f() throws OpenException,NewException{} 注意这里不可以throws父类没有的异常
//因为如果throws父类没有的异常,后面的向上造型是将 Exception3(子类)当成Exception2(父类)的父类中没有声明的异常子类中也不应该声明包含
public Exception3() throws OpenException,NewException{}
//当父类的构造函数声明了异常时,子类也都得声明了这些异常,并且还可以添加自己的异常
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Exception2 e = new Exception3(); //向上造型
e.f();
} catch (OpenException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
流
inputStream与outputStream读的是字节
mark与reset代表读一个流做标记与返回标记处
available代表着是还有多少字节可以读
对于国标码来说汉字两个字占4个字节
对于utcode来说汉字占据两个字符
import java.io.IOException;
public class Buffer {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World");
byte []buffer = new byte[1024];
try {
int len = System.in.read(buffer); //将控制台中的输入以流的形式读入到buffer中
String s = new String(buffer,0,len);//len代表读入的国标码的长度
System.out.println(len);
System.out.println(s.length());//s.length代表读入的unicode的长度
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
flush作用是清空缓冲区
import java.io.*;
public class out {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println();
byte []buffer = new byte[10];
for(int i = 0;i<10;i++)
{
buffer[i] = (byte)i;
}
try {
FileOutputStream out = new FileOutputStream("a.dat");//FileOutputStream只能在a.dat文件中写入单个字节
out.write(buffer);
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}```
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210602012954172.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTU1OTk4,size_16,color_FFFFFF,t_70)
import java.io.*;
public class out {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println();
byte []buffer = new byte[10];
for(int i = 0;i<10;i++)
{
buffer[i] = (byte)i;
}
try {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("a.dat")));//FileOutputStream只能在a.dat文件中写入单个字节
int i = 0xcafebabe;
out.writeInt(i);//调用DataOutputStream类中的方法在内存中写出二进制整型的i
out.close();
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("a.dat")));
int j = in.readInt();//读入成整形的j
System.out.println(j);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210602015859478.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTU1OTk4,size_16,color_FFFFFF,t_70)
DataOutputStream()是写入such as整型(...等等可以写出其他基本类型过滤器,比如一个整型占4个字节;而使用FileInputStream只能写入单个字节),它可以基于BufferOutputStream()(缓冲过滤器)再基于FileInputStream()过滤器.
使用DataOutputStream,FileOnputStream,BufferOutputStream()只能在内存中写入二进制的形式
in.readInt代表直接读入一个整型的类型
**文本流**
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210602165741126.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTU1OTk4,size_16,color_FFFFFF,t_70)
```java
package Buffer;
import java.io.*;
public class Writer {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"))));
//由于目前大多数计算机页码是utf-8,国标码等,需要在将unicode写入时转换成国标码(一个汉字两个字节)等等的形式 ,所以要以FileOutputStream过滤器(只接受字节)打开,
//OutputStreamWriter输入为Stream输出为Writer建立Stream与Writer之间联系
int i = 123456;
out.println(i);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("src/Buffer/Hello.java")));
//读文本文件
String line;
while((line = in.readLine())!=null) //说明栏:若读文本文件时读到最后一行没有了就会返回null
{System.out.println(line);}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FileReader是InputStreamReader(将输入Stream转化为Reader)的一个子类,FileReader可以在一个二进制非unicode文件建立起一个流,如何只有裸的操作文件才用FileReader,且不能做文字的编码处理
BufferedReader类中的readline()方法读入文本文件中一整行
可实现在行之间跳转,可以使用让他跳转到第几行
汉字编码
int i = 123456;
out.println(i);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("utf8.txt"),"utf8"));
// utf8编码形式既包含了一个字节代表一个英文字母短编码形式,又包含了3个字节代表一个汉字的形式,InputStreamReader可以把FileInputStream读入的二进制数据进行转换,jdk默认环境转换方式是国标码,所以应该加入参数utf8,相当于把括号内的("utf8.txt")当作utf8
//读文本文件
String line;
while((line = in.readLine())!=null)
{System.out.println(line);}
格式化输入输出
printf方法与C语言中相同
如果文件是一个二进制的就用InputStream来读,可读入成基本数据类型就用DataInputStream,若文件中表达的是文本,想要读成一整段的文字就用reader来读,想把一段文字解析成各种基本数据类型格式化就用Scanner。
流的应用
package Buffer;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.InetAddress;
public class Yingyong {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Socket socket = new Socket(InetAddress.getByName("localhost"),123456);
//与服务器端连接
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()))
//向服务器端建立输出流
);
out.println("Hello");
out.flush(); //清空缓冲区,避免下一次运行不输出Hello
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream())
//滤波器的底层还是只能InputStream,所以在服务器端未输入时,InputStream的read是阻塞的
);
String line;
line = in.readLine(); //读入服务器端的数据
System.out.println(line);
out.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
对象串行化
package Buffer;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.InetAddress;
class Student
{
private String name;
private int age;
private int grade;
public Student(String name,int age ,int grade)
{
this.age = age;
this.grade = grade;
this.name = name;
}
public String toString() {
return name+" "+age+" "+grade;
}
}
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s1 = new Student("TBY",4,5);
System.out.println(s1);
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("obj.dat"));
out.writeObject(s1); //写入一个类对象s1
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("obj.dat"));
Student s2 = (Student)in.readObject();//readObject()只能返回一个obj类,
//由于我们知道他里面是Student类,所以可以cast
System.out.println(s2); //控制台返回的s2和s1属性相同
in.close();
System.out.println(s1==s2); //返回false证明s1与s2不是一个对象
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
File类
{
File file2 = new File("d:\\develop\\eclipse-workspace\\hi.txt");
System.out.println((file2.lastModified())); //文件2最后一次更改的时间
String[] list = file2.list(); //
for(String k:list) //list()方法是返回某个目录下的所有文件和目录的文件名,返回的是String数组
//listFiles()方法是返回某个目录下所有文件和目录的绝对路径,返回的是File数组
{
System.out.println(k);
}
File[] files = file2.listFiles();
for(File f:files)
{
System.out.println(f);
}
}
public void test4()
{
File file4 = new File("hello.txt");
File file5 = new File("d:\\develop\\eclipse-workspace\\wo.txt");
//public bollean renameTo(File dest); 把文件命名为指定的文件路径
//想要保证返回true,需要file4在硬盘中是存在的,且file5不能在硬盘中存在
boolean bol = file4.renameTo(file5);
System.out.println(bol);
}
public void test5()
{
File file6 = new File("456.txt"); //先把要创建的文件new出来
if(!file6.exists()) //如果file6文件不存在
{
try {
file6.createNewFile(); //创建file6文件
System.out.println("创建成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
file6.delete();
System.out.println("删除成功");
}
}
public void test6()
{
File file2 = new File("d:\\io\\io1");
boolean mkdir = file2.mkdir();
if(mkdir) //如果此文件夹存在,则不创建了
//如果此文件上级目录存在,则也不创建
{
System.out.println("创建成功");
}
File file3 = new File("d:\\io\\io1\\io3");
boolean mkdirs = file2.mkdirs();
if(mkdirs) //如果上层文件目录不存在,一并创建
{
System.out.println("创建成功");
}
}