# 面向对象oop
# 类
# 什么是类?什么是对象?
- 现实世界是由很多对象组成的
基于对象抽出了类 - 对象:真实存在的单个个体
类:类型/类别,代表一类个体 - 类中可以包含:
- 所有对象所共有的属性/特征----------------成员变量
- 所有对象所共有的行为---------------------方法
- 一个类可以创建多个对象
同一类型所创建出来的对象,结构相同,数据不同 - 类是对象的模板,对象是类具体的实例
# 如何创建类?如何创建对象?如何访问成员?
//学生类
public class Student {
//成员变量
String name;
int age;
String address;
//方法
void study(){
System.out.println(name+"在学习...");
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
}
}
package oo.day01;
//学生类的测试类
public class StudentTest {
public static void main(String[] args) {
//创建学生对象
Student zs = new Student();
//给成员变量赋值
zs.name = "zhangsan";
zs.age = 25;
zs.address = "河北廊坊";
//调用方法
zs.study();
zs.sayHi();
Student ls = new Student();
ls.name = "lisi";
ls.age = 27;
ls.address = "黑龙江佳木斯";
ls.study();
ls.sayHi();
//new后所有成员变量都有默认值
Student ww = new Student();
ww.study();
ww.sayHi();
}
}
- shootGame流程(先找对象,基于对象抽类)
- 先找对象:英雄机、天空、小敌机、大敌机、小蜜蜂、子弹
- 抽类:Hero、Sky、Airplane、BigAirplane、Bee、Bullet
- 设计类中的成员变量和方法
- 创建对象并测试
类(数据类型) 引用类型变量 指向 对象 Student zs = new Student(); 基本类型变量(变量) Int a ;
- 补充:
- 类型----------默认值null
- 面向过程的结构化程序设计弊端:java是面向对象的
- 缺乏对数据的封装
- 数据与方法(操作数据)的分离
- 高质量的代码:
- 复用性好、扩展性好、维护性好、
- 可移植性好、健壮性好、可读性好、效率好...
# 方法
- 方法的签名:方法名+参数列表
# 方法的重载(Overload)
- 发生在一个类中,方法名称相同,参数列表不同
- 编译器在编译时会根据方法的签名自动绑定调用的方法
/*
* 补充:
* 1)一个文件中是可以创建多个类的
* 2)public修饰的类只能有一个
* 3)public修饰的类必须与文件名相同
*/
//重载的演示
public class OverloadDemo {
public static void main(String[] args) {
Aoo o = new Aoo();
o.say();
o.say("zhangsan");
o.say(25);
o.say("zhangsan", 25);
o.say(25, "zhangsan");
}
}
class Aoo{
void say(){}
void say(String name){}
void say(int age){}
void say(String name,int age){}
void say(int age,String name){}
//int say(){return 1;} //编译错误,重载与返回值类型无关
//void say(String address){} //编译错误,重载与参数名称无关
}
# 构造方法
- 常常给成员变量赋初值
- 与类同名,没有返回值类型
- 在创建(new)对象时被自动调用
new Student() 调用了Student的构造方法
- 若自己不写构造方法,则编译器默认一个无参构造方法,
TIP
若自己写了构造方法,则不再默认提供
- 构造方法可以重载
# this
- 指代当前对象,哪个对象调用方法指的就是哪个对象
- 只能用在方法中,方法中访问成员变量之前默认有个this.
- this的用法:
- this.成员变量名-----------------访问成员变量 成员变量和局部变量可以同名,但是要用this关键字
- this.方法名()-------------------调用方法(一般不用)
- this()--------------------------调用构造方法
public class Student {
String name;
int age;
String address;
Student(String name){
this(name,0,null); //调构造方法
}
Student(String name,int age){
this(name,age,null);
}
Student(String name,int age,String address){
this.name = name;
this.age = age;
this.address = address;
}
void study(){
System.out.println(name+"在学习...");
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
}
}
# null
- 空,没有指向任何对象
- 若引用的值为null,则该引用不能再进行任何操作了,
- 若操作则发生NullPointerException空指针异常
# 类型画等号
# 引用类型变量之间画等号
- 指向同一个对象
- 通过一个引用对数据的修改会影响另一个引用对数据的访问
eg: 房子钥匙
# 基本类型变量之间画等号
- 赋值
- 对一个变量的修改不会影响另一个变量的值
eg: 身份证复印件
public class NullRefDemo {
public static void main(String[] args) {
Student zs = new Student("zhangsan",25,"LF");
System.out.println(zs.age); //25
Student zss = zs; //指向同一个对象
zss.age = 28;
System.out.println(zs.age); //28
int a = 5;
int b = a; //赋值
a = 8;
System.out.println(b); //5
Student stu = new Student("zhangsan");
System.out.println(stu.name);
stu = null; //空,没有指向任何对象
System.out.println(stu.name); //空指针异常
}
}
# 引用类型数组
1)Student[] stus = new Student[3];
stus[0] = new Student("zhangsan",25,"LF");
stus[1] = new Student("lisi",26,"JMS");
stus[2] = new Student("wangwu",27,"SD");
stus[1].age = 36; //给stus中第2个元素的年龄赋值为36
2)Student[] stus = new Student[]{
new Student("zhangsan",25,"LF"),
new Student("lisi",26,"JMS"),
new Student("wangwu",27,"SD")
};
3)int[][] arr = new int[3][];----------数组的数组
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[2];
arr[1][0] = 100; //给arr中第2个元素中的第1个元素赋值为100
4)int[][] arr = new int[3][4];
//3:为as的长度
//4:为as中每个元素的长度
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
arr[i][j] = 100;
}
}
# 继承
# 继承描述
- 作用:代码复用
- 通过extends来实现继承
- 超类:所有派生类所共有的属性和行为
派生类:派生类所特有的属性和行为 - 派生类继承超类后,派生类具有:超类的+派生类的
- 一个超类可以有多个派生类
一个派生类只能有一个超类-------单一继承 - 继承具有传递性
- java规定:构造派生类之前必须先构造超类
TIP
在派生类的构造方法中若没有调用超类的构造方法
----------则默认super()调用超类的无参构造方法
在派生类的构造方法中若调用了超类的构造方法
----------则不再默认提供
- super()调用超类构造方法,必须位于派生类构造的第1句
# super
指代当前对象的超类对象
- super的用法:
- super.成员变量名-----------------访问超类的成员变量
- super.方法名()-------------------调用超类的方法
- super()--------------------------调用超类的构造方法
//super的演示(含继承)
public class SuperDemo {
public static void main(String[] args) {
Boo o = new Boo();
}
}
class Coo{
Coo(int a){
}
}
class Doo extends Coo{
Doo(){
super(5);
}
/*
//如下代码,写不写都有
Doo(){
super();
}
*/
}
class Aoo{
Aoo(){
System.out.println("超类的构造方法");
}
}
class Boo extends Aoo{
Boo(){
//super(); //默认的(调用超类的构造方法)
System.out.println("派生类的构造方法");
}
}
# 向上造型
- 超类型的引用指向派生类对象
- 能点出来什么,看引用的类型
//向上造型的演示
public class UpLoadDemo {
public static void main(String[] args) {
Aoo o1 = new Aoo();
o1.a = 1;
o1.show();
//o1.b = 2; //编译错误,超类不能访问派生类的
Boo o2 = new Boo();
o2.b = 1;
o2.test();
o2.a = 2; //正确,派生类可以访问超类的
o2.show();
Aoo o3 = new Boo(); //向上造型
o3.a = 1;
o3.show();
//o3.b = 2; //编译错误,能点出来什么,看引用的类型
}
}
class Aoo{
int a;
void show(){}
}
class Boo extends Aoo{
int b;
void test(){}
}
# 方法的重写(Override)
重新写、覆盖
- 发生在父子类中,方法名称相同,参数列表相同,方法体不同
- 重写方法被调用时,看对象的类型
- 重写遵循"两同两小一大"原则:
- 两同:
- 方法名相同
- 参数列表相同
- 方法名相同
- 两小:
- 派生类方法的返回值类型小于或等于超类方法的 - void时,必须相等 - 基本类型时,必须相等 - 引用类型时,小于或等于 - 派生类方法抛出的异常小于或等于超类方法的
- 一大:
- 派生类方法的访问权限大于或等于超类方法的
- 两同:
//超类大,派生类小
class Eoo{
void show(){}
double test(){return 0.0;}
Foo sayHi(){return null;}
Eoo say(){return null;}
}
class Foo extends Eoo{
//int show(){return 1;} //编译错误,void时必须相等
//int test(){return 0;} //编译错误,基本类型时必须相等
//Eoo sayHi(){return null;} //编译错误,引用类型时必须小于或等于
Foo say(){return null;}
}
//测试类,含向上造型与重写
public class Test {
public static void main(String[] args) {
Person[] ps = new Person[5];
ps[0] = new Student("zhangsan",25,"LF","111");
ps[1] = new Student("lisi",22,"JMS","222");
ps[2] = new Teacher("aaa",37,"LF",5000);
ps[3] = new Teacher("bbb",45,"LF",8000);
ps[4] = new Doctor("ddd",35,"LF","主治医师");
for(int i=0;i<ps.length;i++){
System.out.println(ps[i].name);
ps[i].sayHi();
}
/*
Student zs = new Student("zhangsan",25,"LF","111");
Teacher ls = new Teacher("lisi",37,"LF",5000);
Doctor ww = new Doctor("wangwu",35,"LF","主治医师");
zs.sayHi();
ls.sayHi();
ww.sayHi();
*/
/*
Student zs = new Student("zhangsan",25,"LF","111");
//Person zss = new Student("zhangsansan",25,"LF","111");
zs.sayHi();
//zss.sayHi(); //重写方法被调用时,看对象的类型
*/
}
}
class Person{
String name;
int age;
String address;
Person(String name,int age,String address){
this.name = name;
this.age = age;
this.address = address;
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
}
}
class Student extends Person{
String stuId;
Student(String name,int age,String address,String stuId){
super(name,age,address);
this.stuId = stuId;
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address+",学号为:"+stuId);
}
}
class Teacher extends Person{
double salary;
Teacher(String name,int age,String address,double salary){
super(name,age,address);
this.salary = salary;
}
void sayHi(){
System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address+",工资为:"+salary);
}
}
class Doctor extends Person{
String level;
Doctor(String name,int age,String address,String level){
super(name,age,address);
this.level = level;
}
}
# 重写与重载的区别
TIP
常见面试题
- 重写:
- 发生在父子类中,方法名称相同,参数列表相同,方法体不同
- 遵循"运行期绑定",看对象的类型来调用方法
- 重载:
- 发生在一个类中,方法名称相同,参数列表不同,方法体不同
- 遵循"编译期绑定",看引用/参数的类型来绑定方法
TIP
编译期:.java源文件,经过编译,生成.class字节码文件--检测语法
运行期:JVM加载.class并运行.class
Class Aoo{
void show(){}
}
Class Boo extends Aoo{
void show(String name){}//重载
}
package oo.day04;
//重写与重载的演示
public class OverrideOverloadDemo {
public static void main(String[] args) {
Goo goo = new Goo();
Coo o = new Doo();
goo.test(o); //重载看参数/引用(Coo)
}
}
class Goo{
void test(Coo o){
System.out.println("超类型参数");
o.show(); //重写看对象(Doo)
}
void test(Doo o){
System.out.println("派生类型参数");
o.show();
}
}
class Coo{
void show(){
System.out.println("超类show");
}
}
class Doo extends Coo{
void show(){
System.out.println("派生类show");
}
}
补充:
class World{
FlyingObject[] enemies;
FlyingObject[] enemies = null; 什么也没有,空
FlyingObject[] enemies = {}; 有,但是没放东西
FlyingObject[] enemies = new FlyingObject[0];
}
# 包
# package
- 作用:避免类名冲突
- 包名可以有层次结构
- 类的全称为: 包名.类名
- 建议:包名所有字母都小写
# import
- 同包中的类可以直接访问,
不同包中的类不能直接访问,想访问只有如下两种方式: - 先import声明类再使用类----建议
- 类的全称------------------太繁琐,不建议
import引进的一串英文的含义
建议:
域名反写 . 项目名称 . 模块名称 . 类名
cn.tedu . aproject . stumanager .
cn.tedu . aproject . teachermanager .
# 访问控制修饰符
- public:公开的,任何类
- private:私有的,本类
- protected:受保护的,本类、子类、同包类
- 默认的:什么也不写,本类、同包类
TIP
- 类的访问修饰只能是public和默认的
- 类中成员的访问修饰如上四种都可以
WARNING
数据(变量)私有化(private),行为(方法)公开化(public)
# final
最终的、不可改变的---------------应用率低
- 修饰变量:变量不能被改变
- 修饰方法:方法不能被重写
- 修饰类:类不能被继承,但是可以继承别的类
//final的演示
public class FinalDemo {
public static void main(String[] args) {
}
}
/*
* final修饰成员变量,只有如下两种初始化方式:
* 1)声明的同时初始化
* 2)在构造方法中初始化
* final修饰局部变量,在使用之前赋值即可
*/
class Eoo{ //演示final修饰变量
final int a = 5;
final int b;
Eoo(){
b = 6;
}
void test(){
final int c;
//a = 55; //编译错误,final的变量不能被改变
}
}
//演示final修饰方法
class Foo{
final void show(){}
void test(){}
}
class Goo extends Foo{
//void show(){} //编译错误,final的方法不能被重写
void test(){}
}
//演示final修饰类
final class Hoo{}
//class Ioo extends Hoo{} //编译错误,final修饰的类不能被继承
class Joo{}
final class Koo extends Joo{}
# static
静态的
- 静态变量:(static的称为实例变量)
- 由static修饰
- 属于类,存储在方法区(方法区只被加载一次)中,只有一份
- 常常通过类名点来访问
- 何时用:所有对象所共享的数据(图片、音频、视频等)
WARNING
注:结合演示静态变量代码来理解,只有一份
静态方法:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 静态方法中没有隐式的this传递,
静态方法中不能直接访问实例成员 - 何时用:方法的操作仅与参数相关而与对象无关
静态块:
- 属于类,在类被加载期间自动执行,
因类只加载一次,所以静态块也只执行一次 - 何时用:加载/初始化静态资源(图片、音频、视频等)(如果直接初始化而不是用静态块)
- 属于类,在类被加载期间自动执行,
//static的演示
public class StaticDemo {
public static void main(String[] args) {
Loo o1 = new Loo();
o1.show(); //1,1
Loo o2 = new Loo();
o2.show(); //1,2
System.out.println(Loo.b); //2
//System.out.println(o1.b); //不建议通过对象名来访问
Moo.test();
Noo o3 = new Noo();
Noo o4 = new Noo();
}
}
class Loo{ //演示静态变量
int a;
static int b;
Loo(){
a++;
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
}
class Moo{ //演示静态方法
int a;
static int b;
void show(){ //有this
System.out.println(this.a);
System.out.println(Moo.b); 有一个隐式的类名点
}
static void test(){ //没有this
//静态方法没有隐式的this传递
//没有this就意味着没有对象
//而实例成员a必须通过对象点来访问
//System.out.println(a); //编译错误 在a 前加this.就可以
System.out.println(Moo.b); 有一个隐式的类名点
}
}
class Noo{ //演示静态块
static{
System.out.println("静态块");
}
Noo(){
System.out.println("构造方法");
}
}
- static final常量:(一般用public修饰 (是建议))
- 必须声明同时初始化
- 通过类名点来访问,不能被改变
- 建议:常量名所有字母都大写,多个单词用_分隔
- 编译器在编译时将常量直接替换为具体的值,效率高
- 何时用:数据永远不变,并且经常使用
//static final的演示
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI);
//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
//1)加载Boo.class到方法区中
//2)num一并存储在方法区中
//3)到方法区中获取num的值并输出
System.out.println(Boo.num);
//编译器在编译时将常量直接替换为具体的值,效率高
//相当于System.out.println(5);
System.out.println(Boo.COUNT);
}
}
class Boo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
class Aoo{
public static final double PI = 3.1415926;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
# abstract
- 抽象方法:
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
- 抽象类:
- 由abstract修饰
- 包含抽象方法的类必须是抽象类
不包含抽象方法的类也可以声明为抽象类-------我乐意(无意义) - 抽象类不能被实例化(因为抽象方法不完整,所以抽象类也不完整,不能被实例化,也 就式不能被new对象)
- 抽象类都是需要被继承的,派生类:
- 重写抽象类中的所有抽象方法-----变不完整为完整
- 也声明为抽象类-----------------一般不这么做
- 抽象类的意义:
- 封装派生类所共有的属性和行为-----------代码复用
- 为所有派生类提供统一的类型-------------向上造型(向上造型能点出来)
- 可以包含抽象方法,为所有派生类提供统一的入口
- 派生类的具体实现不同,但入口是一致的
补充: int index = 0; //活着的下标 /** 重写getiImage()获取图片*/ public BufferedImage getImage(){ //每10毫秒走一次 if(isLife()){//若活着 return images[index++%2]; //利用这个【index++%2】可以使0,1, 0,1替换,想几个数切换就取余几 } return null; }
# 设计规则
- 将所有派生类所共有的属性和行为,抽到超类中-------抽共性
- 所有派生类的行为都一样,设计为普通方法
- 所有派生类的行为都不一样,设计为抽象方法
# 成员内部类
- 类中套类,里面的称为Inner内部类,外面的称为Outer外部类
- 内部类通常只服务于外部类,对外不具备可见性
- 内部类通常是在外部类中创建的
- 内部类中可以直接访问外部类的成员(包括私有的)
内部类中有一个隐式的引用指向了创建它的外部类对象eg: 外部类名.this.
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不可见
}
}
class Mama{
private String name;
void createBaby(){
Baby b = new Baby(); //内部类对象通常是在外部类中创建的
}
class Baby{
void showMamaName(){
System.out.println(name);
System.out.println(Mama.this.name);
//System.out.println(this.name); //编译错误
}
}
}
# 匿名内部类
- 若想创建一个类的对象,并且对象只被创建一次,
此时该类不必命名,称之为匿名内部类 - jdk1.7(含)版本之前,匿名内部类中想访问外面的变量,(切记) 要求该变量必须是final的
public class NstInnerClassDemo {
public static void main(String[] args) {
//1)创建了Coo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1
//3)大括号中的为派生类的类体
Coo o1 = new Coo(){
};
//1)创建了Coo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2
//3)大括号中的为派生类的类体
Coo o2 = new Coo(){
};
final int num = 5;
Doo o3 = new Doo(){
void show(){
System.out.println("showshow");
System.out.println(num); //1.7(含)以前的版本要求num必须是 final的
}
};
o3.show();
}
}
abstract class Coo{
}
abstract class Doo{
abstract void show();
}
# 补充
- 先写行为(方法):
- 若是某个对象特有的行为,则将行为设计在派生类中
若是所有对象共有的行为,则将行为设计在超类中- 所有派生类行为都一样,设计为普通方法
- 所有派生类行为都不一样,设计为抽象方法,而后派生类重写
- 将部分派生类所共有的行为,设计在接口中
符合既是也是原则时,用接口实现
接口是对继承的单根性的扩展----实现多继承
- 若是某个对象特有的行为,则将行为设计在派生类中
- 窗口调用:
- 定时触发的,在run()中调用
- 事件触发的,在侦听器中调用
- 画出来的,在paint()中调用
# 接口
- 是一种数据类型(引用类型)
- 由interface定义的
- 只能包含常量和抽象方法
- 接口不能被实例化
- 接口是需要被实现/继承的,实现类/派生类:
必须重写接口中的所有抽象方法 - 一个类可以实现多个接口,用逗号分隔
若又继承又实现时,应先继承后实现 - 接口可以继承接口
WARNING
注意:实现的类里面,要尊重重写的两同两小一大规则,也就是重写的方法要加public
TIP
补充:同类型叫继承,不同类叫实现
//接口的演示
public class InterfaceDemo {
public static void main(String[] args) {
//Inter1 o1 = new Inter1(); //编译错误,接口不能被实例化
Inter6 o2 = new Doo(); //向上造型 不同类型的向上造型
Inter5 o3 = new Doo(); //向上造型
}
}
//演示接口继承接口
interface Inter5{
void show();
}
interface Inter6 extends Inter5{
void test();
}
class Doo implements Inter6{
public void show(){}
public void test(){}
}
//演示又继承又实现
interface Inter3{
void show();
}
interface Inter4{
void test();
}
abstract class Boo{
abstract void say();
}
class Coo extends Boo implements Inter3,Inter4{
public void show(){}
public void test(){}
void say(){}
}
//演示接口的实现
interface Inter2{
void show();
void test();
}
class Aoo implements Inter2{
public void show(){}
public void test(){}
}
//演示接口的语法
interface Inter1{
public static final int NUM = 5;
public abstract void show();
int COUNT = 6; //默认public static final
void test(); //默认public abstract
//int number; //编译错误,常量必须声明同时初始化
//void say(){} //编译错误,抽象方法不能有方法体
}
# 多态
# 意义
- 同一类型的引用指向不同的对象时,有不同的实现
--------行为的多态:cut()、run()、step()...- 同一个对象被造型为不同的类型时,有不同的功能
--------对象的多态:我、你、水...
- 同一个对象被造型为不同的类型时,有不同的功能
# 向上造型/自动类型转换:
- 超类型的引用指向派生类的对象
- 能造型成为的类型有:超类+所实现的接口
- 能点出来什么,看引用的类型
# 强制类型转换
成功的条件只有如下两种:
- 引用所指向的对象就是该类型
- 引用所指向的对象实现了该接口/继承了该类
WARNING
强转若不符合如上两个条件,则发生ClassCastException类型转换异常
TIP
建议:强转之前先通过instance of来判断引用所指向的对象是否是该类型
//多态的演示
public class MultiTypeDemo {
public static void main(String[] args) {
Aoo o = new Boo(); //向上造型(自动类型转换)
Boo o1 = (Boo)o; //引用o所指向的对象就是Boo
Inter1 o2 = (Inter1)o; //引用o所指向的对象实现了Inter1
//Coo o3 = (Coo)o; //ClassCastException类型转换异常
if(o instanceof Coo){ //false
Coo o4 = (Coo)o; 注意:引用类型做强转一定要判断
}
System.out.println("over");
}
}
interface Inter1{
}
class Aoo{
}
class Boo extends Aoo implements Inter1{
}
class Coo extends Aoo{
}
# 内存管理
由JVM来管理
# 堆
- 存储new出来的对象(包括实例变量)
- 垃圾:没有任何引用所指向的对象,
垃圾回收器(GC)不定时到内存中清扫垃圾,
回收过程是透明的(看不到的),不一定一发现垃圾就立刻回收,
调用System.gc()可以建议虚拟机尽快调度GC来回收垃圾 - 实例变量的生命周期:
创建对象时存在堆中,对象被回收时一并被回收 - 内存泄漏:不再使用的对象还没有被及时的回收(小面试题)
建议:不再使用的对象及时将引用设置为null
# 栈
- 正在调用的方法中的局部变量(包括方法的参数)
- 调用方法时,在栈中为该方法分配一块对应的栈帧,
栈帧中存储方法中的局部变量(包括方法的参数),
方法调用结束时,栈帧被清除,局部变量一并被清除 - 局部变量的生命周期:
方法调用时存储在栈中,方法结束时与栈帧一并被清除
# 方法区
- 存储.class字节码文件(包括方法、静态变量)
- 方法只有一份,通过this来区分具体的访问对象
/**
* 解释同一个类型的引用画等号后,指向堆中的同一个对象
* 引用类型与基本类型画等号的区别
*/
public class RefDemo {
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = stu1;
stu1.age = 18;
stu2.age = 88;
System.out.println(stu1.age);
int a = 1;
int b = 2;
b=a;
System.out.println(a);
}
}
class Student {
int age;
int name;
}
# 面向对象总结
# 设计规则
- 将所有派生类所共有的属性和行为,抽到超类中-------抽共性
- 所有派生类的行为都一样,设计为普通方法
所有派生类的行为都不一样,设计为抽象方法 - 将部分派生类所共有的行为,抽到接口中
符合既是也是原则时,使用接口
接口是对继承的单根性的扩展------------多继承
# 面向对象三大特征
- 封装:
- 类:封装的是对象的属性的行为
- 方法:封装一段特定的业务逻辑功能
- 访问控制修饰符:封装的是具体的访问权限
- 继承:
- 作用:代码复用
- 超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的行为
派生类:派生类所特有的属性和行为 - 单一继承、多接口实现,传递性
- 多态:
- 行为多态(所有抽象方法都是多态的)
对象多态(所有对象都是多态的) - 向上造型、强制类型转换、instance of
- 多态的表现形式:
- 重写:根据对象的不同来多态
- 重载:根据参数的不同来多态
- 行为多态(所有抽象方法都是多态的)
# debug
- 何时用:当程序的运行结果与你的预期不同时,需要调试
- 调试方式:
- 打桩: System.out.println(数据);
- Debug调试工具:
- 添加断点
- F5:单步调试(会进入到方法中)
- F6:逐过程调试(不会进入到方法中)
- F7:结束方法的调试(从方法中返回)
- F5:单步调试(会进入到方法中)
- F8:直接跳到下一个断点(若后面无断点则结束调试)
- 会看两个东西:
- 会看变量
- 添加监视 (在debug中选中变量,然后右键,选择watch)
# 补充
- 私有的数据无法使用的时候,就创建一个公开的方法get一下。
- Java中所有类都会继承object
- 清理现场就是用原来引用指向一个新创建的对象,原来创建的对象就会被当作垃圾回收
实例变量
变量
静态变量
注:这里的实例变量就是成员变量