20145218 《Java程序设计》第四周学习总结
2016-03-26 15:34
701 查看
20145218 《Java程序设计》第四周学习总结
教材学习内容总结
继承
继承共同行为
继承基本上就是避免多个类间重复定义共同行为。继承的三个好处:减少代码冗余;维护变得简单;扩展变得容易。
构造方法不能被继承。
代码如下:
public class RPG1 { public static void main (String[] args) { demoSwordsMan(); demoMagician(); } static void demoSwordsMan() { SwordsMan1 swordsMan1 = new SwordsMan1(); swordsMan1.setName("Justin"); swordsMan1.setLevel(1); swordsMan1.setBlood(200); System.out.printf("剑士 : (%s, %d, %d)%n",swordsMan1.getName(), swordsMan1.getLevel(),swordsMan1.getBlood()); } static void demoMagician() { Magician1 magician = new Magician1(); magician.setName("Moinca"); magician.setLevel(1); magician.setBlood(100); System.out.printf("魔法师 :(%s ,%d ,%d)%n",magician.getName(), magician.getLevel(),magician.getBlood()); } }
运行结果截图如下:
多态与is-a
is-a代表的是类之间的继承关系。中文称为“是一种”关系。使用是一种原则,就可以判断何时编译成功,何时编译失败。
编译程序会检查父子类间的“是一种”关系.
定义继承需要注意:类与类之间要有是一种(is-a)关系,比如SwordsMan继承了Role,所以SwordsMan is a Role。
代码如下:
public class RPG2 { public static void main(String[] args) { SwordsMan swordsMan = new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); Magician magician = new Magician(); magician.setName("Monica"); magician.setLevel(1); magician.setBlood(100); showBlood(swordsMan); showBlood(magician); } static void showBlood(Role role) { System.out.printf("%s 血量 %d%n",role.getName(),role.getBlood()); } }
运行结果截图如下:
重新定义行为
重新定义:在继承父类之后,定义与父类中相同的方法部署,但实行内容不同。代码如下:
public class RPG3 { public static void main(String[] args) { SwordsMan3 swordsMan3 = new SwordsMan3(); swordsMan3.setName("Justin"); swordsMan3.setLevel(1); swordsMan3.setBlood(200); Magician3 magician3 = new Magician3(); magician3.setName("Monica"); magician3.setLevel(1); magician3.setBlood(100); drawFight(swordsMan3); drawFight(magician3); } static void drawFight(Role3 role) { System.out.print(role.getName()); role.fight3(); } }
运行结果截图如下:
继承语法细节
protected成员
protected与private基本相似,只有在继承时有较大的区别。继承的类可以访问protected成员,但是不能访问private成员。被声明为protected的成员,相同包中的类可以直接存取,不同包中的类可以在继承后的子类直接存取。
权限关键字与范围
关键字 类内部 相同包类 不同包类
public 可存取 可存取 可存取
protected 可存取 可存取 子类可存取
private 可存取 不可存取 不可存取
练习代码如下:
public abstract class Role5 { protected String name; protected int level; protected int blood; public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Magician5 extends Role5 { public void fight() { System.out.println("魔法攻击"); } public void cure() { System.out.println("魔法治疗"); } public String toString() { return String.format("魔法师 (%s, %d, %d)", this.name, this.level, this.blood); } } public class SwordsMan5 extends Role5 { public void fight() { System.out.println("挥剑"); } public String toString() { return String.format("剑士 (%s, %d %d)", this.name, this.level, this.blood); } }
重新定义的细节
对于父类中的方法权限,只能扩大但不能缩小。若原来成员public,子类中重新定义时不可为private或protected。练习代码如下:
public abstract class Role6 { public String toString() { return String.format("(%s, %d, %d)", this.name, this.level, this.blood); } }
再看构造函数
如果类有继承关系,在创建子类实例后,会先进行父类定义的初始流程,再进行子类中的初始流程,也就是创建子类实例后,会先执行父类构造函数定义的流程,再执行子类构造函数定义的流程。构造函数可以重载,父类中可重载多个构造函数,如果子类构造函数中没有指定执行父类中哪个构造函数,默认会调用父类中无参数构造函数。
this()与super()只能择一调用,而且一定要在构造函数第一行执行。
再看final关键字
若class前使用了final关键字定义,那么这个类不会有子类,不能被继承。子类不可以重新定义final方法。
final可以修饰类,方法,变量。
final修饰的方法不可以被覆盖。
final修饰的变量是一个常量,只能被赋值一次。
内部类只能访问被final修饰的局部变量。
java.lang.Object
子类只能继承一个父类,如果定义类时没有使用extends关键字指定继承任何类,那就是继承java.lang.Object。相当于public class Some Object{...}Java中所有对象,一定“是一种”Object。
任何类型的对象,都可以使用Object声明的名称来参考。
练习代码如下:
import java.util.Arrays; public class ArrayList { private Object[] list; private int next; public ArrayList(int capacity) { list=new Object[capacity]; } public ArrayList() { this(16); } public void add(Object o) { if(next==list.length) { list=Arrays.copyOf(list, list.length*2); } list[next++]=o; } public Object get(int index) { return list[index]; } public int size() { return next; } } import java.util.Scanner; import static java.lang.System.out; public class Guest { public static void main(String[] args) { ArrayList names=new ArrayList(); collectNameTo(names); out.println("访客名单:"); printUpperCase(names); } static void collectNameTo(ArrayList names) { Scanner console=new Scanner(System.in); while(true) { out.print("访客名称:"); String name=console.nextLine(); if(name.equals("quit")) { break; } names.add(name); } } static void printUpperCase(ArrayList names) { for(int i=0;i<names.size();i++) { String name=(String) names.get(i); out.println(name.toUpperCase()); } } }
代码运行结果如下:
关于垃圾收集
程序执行流程中无法通过变量参考的某个对象,就是徒耗内存的垃圾。jvm有垃圾收集机制(GC),收集到的垃圾对象所占据的内存空间,会被垃圾收集器释放。
再看抽象类
练习代码如下:public abstract class GuessGame { public void go() { int number=(int)(Math.random()*10); int guess; do { print("输入数字:"); guess=nextInt(); }while(guess!=number); println("猜中了"); } public void println(String text) { print(text+"\n"); } public abstract void print(String text); public abstract int nextInt(); } import java.util.Scanner; public class ConsoleGame extends GuessGame { private Scanner scanner=new Scanner(System.in); @Override public void print(String text) { System.out.print(text); } @Override public void println(String text) { System.out.println(text); } @Override public int nextInt() { return scanner.nextInt(); } } public class Guess { public static void main(String[] args){ GuessGame game=new ConsoleGame(); game.go(); } }
代码运行结果如下:
接口
接口定义行为
接口可以用于定义行为但不定义操作。对于“定义行为”,可以使用interface关键字定义,接口中的方法不能操作,直接标示为abstract,而且一定是
类要操作接口,必须使用implements关键字。操作某接口时,对接口中定义的方法有两种处理方式,一是操作接口中定义的方法,二是再度将该方法标示为abstract。
继承会有“是一种”关系,接口操作则表示“拥有行为”,但不会有“是一种”关系。
练习代码如下:
public abstract class Fish implements Swimmer { protected String name; public Fish(String name){ this.name = name; } public String getName() { return name; } @Override public abstract void swim(); } public class Human implements Swimmer { private String name; public Human(String name){ this.name=name; } public String getName() { return name; } @Override public void swim() { System.out.printf("人类 %s 游泳 %n",name); } }
行为的多态
接口多态语法的判断,方式是“右边是不是拥有左边的行为”或者“右边对象是不是操作了左边接口”。练习代码如下:
public class Ocean{ public static void main(String[] args) { doSwim(new Anemonefish("尼莫")); doSwim(new Shark("兰尼")); doSwim(new Human("贾斯汀")); doSwim(new Submarine("黄色一号")); } static void doSwim(Swimmer swimmer){ swimmer.swim(); } }
运行结果如下:
解决需求变化
有弹性、具可维护性的程序:如果增加新的需求,原有的程序无需修改,只需针对新需求撰写程序。练习代码如下:
public interface Flyer { public abstract void fly(); } public class FlyingFish extends Fish implements Flyer{ public FlyingFish(String name){ super(name); } @Override public void swim(){ System.out.println("飞鱼游泳"); } @Override public void fly(){ System.out.println("飞鱼会飞"); } } public class Airplane implements Flyer{ protected String name; public Airplane(String name){ this.name=name; } @Override public void fly(){ System.out.printf("飞机 %s 在飞%n",name); } } public class Ocean2{ public static void main(String[] args) { doSwim(new Anemonefish("尼莫")); doSwim(new Shark("兰尼")); doSwim(new Human("贾斯汀")); doSwim(new Submarine("黄色一号")); doSwim(new Seaplane("空军零号")); doSwim(new FlyingFish("甚平")); } static void doSwim(Swimmer swimmer) { swimmer.swim(); } }
接口语法细节
接口的默认
在java中,可使用interface来定义抽象的行为与外观,如接口中的方法可声明为public abstract。类可以操作两个以上的类,也就是拥有两种以上的行为。类可以同时继承某个类,并操作某些接口。
接口可以继承另一个接口,也就是继承父接口行为,再在子接口中额外定义行为。
练习代码如下:
public interface Action{ public static final int STOP=0; public static final int RIGHT=1; public static final int LEFT=2; public static final int UP=3; public static final int DOWN=4; } import static java.lang.System.out; public class Game{ public static void main(String[] args){ play(Action.RIGHT); play(Action.UP); } public static void play(int action){ switch(action){ case Action.STOP: out.println("bofangtingzhidonghua"); break; case Action.RIGHT: out.println("bofangxiangyoudonghua"); break; case Action.LEFT: out.println("bofangxiangzuodonghua"); break; case Action.UP: out.println("bofangxiangshangdonghua"); break; case Action.DOWN: out.println("bofangxiangxiadonghua"); break; default: out.println("buzhichicidongzuo"); } } }
运行结果如下:
匿名内部类
临时继承某个类或操作某个接口并建立实例,可使用匿名内部类。匿名内部类语法为:new 父类()|接口(){// 类本体操作 };
练习代码如下:
public class Client{ public final String ip; public final String name; public Client(String ip,String name){ this.ip=ip; this.name=name; } } public class ClientEvent{ private Client client; public ClientEvent(Client client){ this.client=client; } public String getName(){ return client.name; } public String getIp(){ return client.ip; } } public interface ClientListener{ void clientAdded(ClientEvent event); void clientRemoved(ClientEvent event); } import java.util.ArrayList; public class ClientQueue{ private ArrayList clients=new ArrayList(); private ArrayList listeners=new ArrayList(); public void addClientListener(ClientListener listener){ listeners.add(listener); } public void add(Client client){ clients.add(client); ClientEvent event=new ClientEvent(client); for(int i=0;i<listeners.size();i++){ ClientListener listener=(ClientListener) listener.get(i); listener.client.Added(event); } } public void remove(Client client){ client.remove(client); ClientEvent event=new ClientEvent(client); for(int i=0;i<listeners.size();i++){ ClientListener listener=(ClientListener) listener.get(i); listener.client.Removed(event); } } } public class Multichat{ public static void main(String[] args){ Client c1=new Client("127.0.0.1","Caterpillar"); Client c1=new Client("192.168.0.2","Justin"); ClientQueue queue=new ClientQueue(); queue.addClientListener(new ClientListener(){ @Override public void clientAdded(ClientEvent event){ System.out.printf("%s cong %s 联机%n", event.getGame(),event.getIp()); } @Override public void clientRemoved(ClientEvent event){ System.out.printf("%s cong %s 脱机%n", event.getGame(),event.getIp()); } }); queue.add(c1); queue.add(c2); queue.remove(c1); queue.remove(c1); } }
运行结果如下:
使用enum枚举常数
练习代码如下:public enum Action2{ STOP,RIGHT,LEFT,UP,DOWN } import static java.lang.System.out; public class Game2{ public static void main(String[] args){ play(Action.RIGHT); play(Action.UP); } public static void play(Action action){ switch(action){ case STOP: out.println("bofangtingzhidonghua"); break; case RIGHT: out.println("bofangxiangyoudonghua"); break; case LEFT: out.println("bofangxiangzuodonghua"); break; case UP: out.println("bofangxiangshangdonghua"); break; case DOWN: out.println("bofangxiangxiadonghua"); break; } } }
运行结果如下:
代码调试中的问题和解决过程
课本上的代码只有两个是可以在cmd中运行的,其余的只可以在idea中运行。本周代码托管截图
感悟
Java的学习已经入第四周,之前总是拖到周末去看视频,写博客,而第四周显然不可以再拖沓了,课本深度的增加,代码难度的加强,都是督促我们学习的动力。与前三周不同的是,这周的代码不是独立的,而是几组代码组合在一起才能运行。而且在cmd中可以运行的少之又少,只得在之前不是很熟悉的IDE中运行。但学习任务难度的加大也不是只提供压力,而是转变为学习的动力,在第四周我每天都会抽出时间来学习Java,也熟练掌握了之前没使用过的IDE,并且学会了用wc统计代码行数,这周的学习可谓是获益匪浅。学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 1/3 | 18/40 | |
第三周 | 400/1000 | 1/4 | 25/60 | |
第四周 | 1292/1300 | 1/5 | 30/90 |
参考资料
Java学习笔记(第8版)《Java学习笔记(第8版)》学习指导
相关文章推荐
- struts的DevMode模式问题
- Java Vector 类
- java中静态代码块的用法 static用法详解
- Java线程总结
- for 循环中植入两个变量
- 转 spring 常用工具类
- Notification的用法
- (转)java.util.ResourceBundle使用详解
- Java笔记---CenOS下配置Mysql
- java二十二节-输入输出总结
- Java中Class类浅谈
- Java学习笔记--ThreadLocal
- Java volatile
- Java程序编译&运行笔记
- Java反射机制浅谈
- js中使用encodeURIComponent编码url后java后台的解码
- Struts2学习(一)
- myeclipse 启动时 server Could not create the view: An unexpected exception was thrown.
- Java多线程之volatile变量
- spring学习笔记(24)基于注解配置事务