23号
一、eclipse使用技巧
ctrl + T 查看继承树状态。
二、关于package
1.Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
2.如果导入两个同名的类,只能用包名+类名来显示调用相关类:
java.util.Date date = new java.util.Date();
25号
一、super关键字
super是直接父类对象的引用。
若是构造方法的第一行代码没有显式的调用super(…)或者this(…);那么Java默认都会调用super(),含义是调用父类的无参数构造方法。
二、继承树追溯
构造方法第一句总是:super(…)来调用父类对应的构造方法。所以,流程就是:先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。
三、访问控制符
1、private 表示私有,只有自己类能访问
2、default表示没有修饰符修饰,只有同一个包的类能访问
3、protected表示可以被同一个包的类以及其他包中的子类访问
4、public表示可以被该项目的所有包中的所有类访问
26号
一、Eclipse常用快捷键
1、单词补全:Alt+/
2、删除行:Ctrl+D
3、在当前行上插入一行:Ctrl+Shift+Enter
4、在当前行下插入一行: Shift+Enter
5、快速添加注释:Ctrl+/
二、Javabean封装
1、一般使用private访问权限。
2、用get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作
eclipse中还可以快速构造方法:
三、多态的要点
继承,方法重写,父类引用指向子类对象。
四、final关键字的作用
1、修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
2、修饰方法:该方法不可被子类重写。但是可以被重载。
3、修饰类: 修饰的类不能被继承。比如:Math、String等。
27号
一、数组初始化
数组的初始化方式总共有三种:静态初始化、动态初始化、默认初始化。
//静态初始化
int [] a = {1,2,3};//静态初始化基本类型数组;
Man[] mans = {new Man(1,1),new Man(1,2)};//静态初始化引用类型数组;
//动态初始化
int [] a1 = new int[2];//分配空间
a1[0] = 1;//给数组元素赋值
a1[1] = 2;
//默认初始化
int a2[] = new int[2];//默认值:0,0
另注:for-each循环
专门用于读取数组或集合中所有的元素,即对数组进行遍历。
语句格式:
for(元素类型t 元素变量x : 遍历对象obj){
引用了x的java语句;
}
二、碰撞球游戏项目
1、AWT技术画出游戏主窗口
JFrame类默认没有处理关闭窗口功能,我们需要自己添加关闭功能。System.exit(0)表示应用正常结束。addWindowListener()表示增加窗口监听事件。
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
2、图形和文本绘制
使用paint()方法,它会被系统自动调用,画出整个窗口及其内部内容。
当出现黑屏,前面加上super.paint(g);
表示再原有基础上重绘。
3、ImageIO实现图片加载技术
4、多线程和内部类实现动画效果
PaintThread方法:按照线程40ms画一次,1秒大约调用25次(1秒=1000ms)。就能在人眼实现动画的效果。
while(true) {
System.out.println("重画!");
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
launchFrame方法:启动重画线程代码
public void launchFrame(){
...
new PaintThread().start(); //启动重画线程
}
28号
续上,碰撞球项目:
5、GameObject类设计
窗口中所有的对象(球)都有很多共性:坐标位置、运行速度、宽度和高度”。为了方便程序开发,可以设计一个GameObject类,它可以作为所有游戏物体的父类,方便编程。
public class GameObject {
Image img;
double x,y;
int speed;
int width,height;
...
6、键盘控制
键盘和程序交互时,每次按下键、松开键都会触发相应的键盘事件,事件的信息都封装到了KeyEvent对象中。每个按键都对应相应的数字,我们都可以通过KeyEvent对象来查询,通过对应的数字做出不同的坐标运算,这样就可以由方向键控制小球移动。
7、随机碰撞球类基本设计
用AWT技术画出碰撞球,设计方向随机,并且遇到边界会反弹。
8、容器对象存储
通过定义一个容器ArrayList来管理这些对象。在paint方法中遍历容器中所有对象,并画出这些碰撞球。
ArrayList<Shell> shellList = new ArrayList<Shell>();
9、矩形碰撞检测
Java的API中,为我们提供了Rectangle类来表示矩形相关信息,并且提供了intersects()方法,直接判断矩形是否相交。
//控制球和碰撞球对象进行矩形检测
boolean peng = b.getRect().intersects(plane.getRect());
10、爆炸效果的实现
在碰撞后的坐标轮播画出爆炸图片,就显示爆炸效果。
29号
续上,碰撞球项目:
11、 计时功能
计算当前时刻和游戏结束时刻之差
最终效果展示
一、抽象方法和抽象类
使用abstract修饰的方法是抽象方法。
包含抽象方法的类就是抽象类。
使用要点:
1、有抽象方法的类只能定义成抽象类。
2、抽象类不能实例化,即不能用new来实例化抽象类。
3、抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用。
4、抽象类只能用来被继承。
5、抽象方法必须被子类实现。
通过抽象类,可以做到严格限制子类的设计,使子类之间更加通用。意思就是子类方法必须重写拉,否则会报错!
二、接口
接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。
声明格式:
[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
常量定义;
方法定义;
}
定义接口的详细说明:
- 访问修饰符:只能是public或默认。
- 接口名:和类名采用相同命名机制。
- extends:接口可以多继承。
- 常量:接口中的属性只能是常量,总是:public static final 修饰。即使省略也是public static final。
- 方法:接口中的方法只能是:public abstract。 即使省略也会是默认public abstract。
三、内部类
作用:
1、内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
2、内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。 但外部类不能访问内部类的内部属性。
使用场合:
1、在只为外部类提供服务的情况下可以优先考虑使用内部类。
2、每个内部类都能独立地继承一个类或者实现某些接口,所以无论外部类是否已经继承了某个类或者实现了某些接口,对于内部类没有任何影响。
内部类的分类:
在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。
++++++++++++++++++++++++
非静态内部类:
1、非静态内部类必须寄存在一个外部类对象里。
2、非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
3、非静态内部类不能有静态方法、静态属性和静态初始化块。
Outer.Inner inner = new Outer().new Inner();
++++++++++++++++++++++++
静态内部类:
静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过 new 静态内部类()访问静态内部类的实例。
Outerx.Inner inner = new Outerx.Inner();
++++++++++++++++++++++++
匿名内部类
适合那种只需要使用一次的类。比如:键盘监听操作等等。但看不太懂。
++++++++++++++++++++++++
局部内部类
比较少用,了解即可。
四、一些小问题
eclipse 出现 debug Line breakpoint
点击这个按钮即可
30号
一、阅读API文档
打开网址并下载。
www.oracle.com/technetwork/java/javase/documentation/jdk8-doc-downloads-2133158.html
解压zip,点击进入index.html即可
二、数组的拷贝
System类里包含了一个static void arraycopy(object src,int srcpos,object dest, int destpos,int length)方法,通过它可以实现数组拷贝。
参数:
object src:源数组
int srcpos:源数组起始位置
object dest:目标数组
int destpos:目标数组下标位置
int length:复制的长度
通过arraycopy方法,可以实现数组的增添,删除等扩展功能。
三、java.util.Arrays类
JDK提供的java.util.Arrays类,包含了常用的数组操作,方便我们日常开发。Arrays类包含了:排序、查找、填充、打印内容等常见的操作。
打印:
Arrays.toString()
此方法是Arrays类的静态方法,不是Object的toString()方法。
System.out.println(a); // 打印数组引用的值;
System.out.println(Arrays.toString(a)); // 打印数组元素的值;
排序:
Arrays.sort();
Arrays类还包含其他方法,日后学习多多练习。
四、包装类
我们基本数据类型不是对象,但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。而包装类就是为了让这些基本数据拥有方法和属性。
在这八个类中,除了Character和Boolean以外,其他的都是“数字型”,“数字型”都是java.lang.Number的子类。Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。
包装类的用途:
1、包装类包含每种基本数据类型的相关属性如最大值、最小值等。
2、基本类型可以和包装类型直接相互转换。
自动装箱和拆箱:
将基本数据类型和包装类之间进行自动的互相转换。
自动装箱
Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是valueOf(100),而不是new Integer(100)
自动拆箱
Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();
包装类空指针异常问题
public class Test2 {
public static void main(String[] args) {
Integer c = null;
int d = c; // 此处其实就是:c.intValue(),因此抛空指针异常。
}
}
包装类的缓存问题
整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
//测试代码
public class TestArrOf {
public static void main(String[] args) {
Integer in1 = -128;
Integer in2 = -128;
System.out.println(in1 == in2);//true 因为123在缓存范围内
System.out.println(in1.equals(in2));//true
Integer in3 = 1234;
Integer in4 = 1234;
System.out.println(in3 == in4);//false 因为1234不在缓存范围内
System.out.println(in3.equals(in4));//true
}
}
包装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用equals方法。
31号
一、String类,StringBuffer类和StringBuilder类
String 类对象代表不可变的Unicode字符序列。即String对象为“不可变对象”,对象内部的成员变量的值无法再改变。
StringBuffer和StringBuilder非常类似,均代表可变的字符序列。 这两个类都是抽象类AbstractStringBuilder的子类,方法几乎一模一样。
两者区别:
StringBuffer线程安全,做线程同步检查, 效率较低。
StringBuilder线程不安全,不做线程同步检查,因此效率较高。 建议采用该类。
String使用的陷阱
String一经初始化后,就不会再改变其内容了。对String字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。比如:
String s =“a”; 创建了一个字符串
s = s+“b”; 实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+“b”(也就是"ab")。 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。
for (int i = 0; i < 5000; i++) {
str8 = str8 + i;//相当于产生了10000个对象
}
相反,StringBuilder和StringBuffer类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。
for (int i = 0; i < 5000; i++) {
sb1.append(i);
}
二、时间处理相关类
1、Date时间类
2、DateFormat类和SimpleDateFormat类
DateFormat类:把时间对象转化成指定格式的字符串。
SimpleDateFormat类:把指定格式的字符串转化成时间对象。
3、Calendar日历类
Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。
GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。
写一个可视化日历,展示如图:
贴下代码
package cn.sxt.o0;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class TestCalendar2 {
public static void main(String[] args) throws ParseException{
System.out.println("请输入日期(格式:2021-1-31):");
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = df.parse(str);
Calendar c = new GregorianCalendar();
c.setTime(date);
int day = c.get(Calendar.DAY_OF_MONTH);
int days = c.getActualMaximum(Calendar.DATE);//getActualMaximum()方法获得本月天数
System.out.println("日\t一\t二\t三\t四\t五\t六");
c.set(Calendar.DAY_OF_MONTH,1);
for(int i=0;i<c.get(Calendar.DAY_OF_WEEK)-1;i++) {
System.out.print("\t");
}
for(int i=1;i<=days;i++) {
if(day == c.get(Calendar.DAY_OF_MONTH)) {
System.out.print(c.get(Calendar.DAY_OF_MONTH)+"*\t");//标记*号
}else {
System.out.print(c.get(Calendar.DAY_OF_MONTH)+"\t");
}
if(c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
System.out.println();//换行
}
c.add(Calendar.DAY_OF_MONTH, 1);
}
}
}