内存管理
Java程序所需内存由JVM来管理,分配
堆
- 存储所有new出来的对象
- 成员变量的生命周期:
创建对象时存储在堆中,对象回收时一并消失 - 没有任何引用指向的对象称为垃圾
垃圾回收器(GC)不定时清扫垃圾,发现垃圾则自动清理 - 内存泄露:不再使用的内存没有被及时的释放
建议:不再使用的对象及时将引用设置为null - 垃圾回收过程是透明的
- 调用System.gc()建议虚拟机尽快回收垃圾
栈
- 用于存储方法被执行时所有的局部变量
- 调用方法时为该方法分配对应的栈桢,栈桢中存储所有的局部变量
方法执行结束时栈桢被清除,局部变量也一并消失 - 局部变量与成员变量的区别:
*成员变量:类中方法外,new对象时存在堆中,有默认值
*局部变量:方法中,调方法时存在栈中,没有默认值
方法区
- 用于存储.class字节码文件以及方法
- 方法只有一份,通过this区分到底哪个对象调用的
继承
- 避免代码重复,有利于代码的重用,通过extends关键字继承
- 父类/基类:所有子类所共有的变量和方法
子类/派生类:子类所特有的变量和方法 - 继承后子类具有:子类的+父类的成员变量和方法
- 一个父类可以有多个子类
一个子类只能继承一个父类—-单一继承 - 继承具有传递性 父类-子类-孙类……
- java规定:构造子类之前必须先构造父类
子类构造中若没有调用父类构造方法,则默认super()来调父类的无参构造
若子类自己调了,则不再默认提供 - super调用父类构造必须位于子类构造的第一句
- 注意事项:
子类不能继承父类的构造方法,只能调用
继承要符合is a的关系,千万不要单单为了重用代码而继承 - super关键字指代当前对象的父类对象
- super用法:
*super.成员变量名———访问父类的成员变量
*super.方法名()————调用父类的方法
*super()———————-调用父类的构造方法
向上造型
- 父类型的引用指向子类的对象
Tetromino a1=new T();Tetromino a2=new J(); - 能点出来什么,看引用的类型
子类可以点出父类的成员变量和方法,父类点不出子类的来
DeBug
- 帮助找错,前提–知道代码出错了
- F5—逐步调试(进方法内)
F6—逐方法调试(不进方法内)
F7—返回方法
F8—跳到下一个断点,或者结束
案例
1.创建一个格子类
public class Cell {
int row;
int col;
Cell(){ //无参构造方法
this(0,0); //this关键字调用有参构造方法
}
Cell(int row,int col){ //有参构造方法
this.row=row;
this.col=col;
}
String coord(){ //打印坐标
return row+","+col;
}
2.创建一个父类
//父类
public class Tetromino {
Cell[] cells;
Tetromino(){
cells=new Cell[4];
}
void drop(){ //图形下落一行
for(int i=0;i<cells.length;i++){
cells[i].row++;
}
}
void moveLeft(){ //图形左移一列
for(int i=0;i<cells.length;i++){
cells[i].col--;
}
}
void moveRight(){ //图形右移一列
for(int i=0;i<cells.length;i++){
cells[i].col++;
}
}
void print(){ //打印图形坐标
for(int i=0;i<cells.length;i++){
String str=cells[i].coord();
System.out.println(str);
}
}
}
3.创建一个T型子类
//子类
public class T extends Tetromino{
T(int row,int col){
super(); //系统默认提供的super()调用父类的无参构造方法
cells[0]=new Cell(row,col);
cells[1]=new Cell(row,col+1);
cells[2]=new Cell(row,col+2);
cells[3]=new Cell(row+1,col+1);
}
}
4.创建CellGame类
//打印场地及图形位置,并实现操作以及向上造型的演示
import java.util.Scanner;
public class CellGame {
public static void main(String[] args) {
/*
T t=new T(2,5); //创建一个子类对象
printGraph(t); //调用方法 传值同时造型
Tetromino a=new T(1,2);//向上造型
printGraph(a); //先造型再传值
*/
Scanner sc=new Scanner(System.in);
System.out.print("请输入图形第一个格子初始坐标:");
int row=sc.nextInt();
int col=sc.nextInt();
T t=new T(row,col);
System.out.println("图形初始位置:");
printGraph(t);
do{
System.out.print("请输入操作(1.下落一行,2.左移一列,3.右移一列,0.退出):");
int x=sc.nextInt();
if(x==0){
System.out.println("欢迎再来!");
break;
}else{
switch(x){
case 1:t.drop();
printGraph(t);
break;
case 2:t.moveLeft();
printGraph(t);
break;
case 3:t.moveRight();
printGraph(t);
break;
default :System.out.println("输入有误!");
}
}
}while(true);
}
//打印墙和图形
public static void printGraph(Tetromino t){ //参数类型为父类,所以可以传他的任何一个子类
for(int i=0;i<20;i++){
for(int j=0;j<10;j++){
boolean flag=false; //开关语句 先判断打-
for(int k=0;k<t.cells.length;k++){
if(t.cells[k].row==i&&t.cells[k].col==j){
flag=true; //变为打*
break; //判断一个格子符合条件则跳出循环
}
}
if(flag==true){
System.out.print("* ");
}else{
System.out.print("- ");
}
}
System.out.println();
}
}
}