OO:面向对象
-
OOA:面向对象分析
-
OOD:面向对象设计
-
OOP:面向对象编程
三大基本特征:
- 封装
- 继承
- 多态
什么是高质量的代码?:
- 复用性好、扩展性好、维护性好、可移植性好、健壮性好、可读性好、效率好…
类: 是一种引用数据类型(是我们自己创造的一种数据类型),默认值null。
构造方法: 构造函数、构造器、构建器---------------复用给成员变量赋初始值代码
作用:给成员变量赋初始值
- 与类同名,没有返回值类型(连void都没有)
- 在创建(new)对象时被自动调用
- 若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了,则不再默认提供
- 构造方法可以重载
this: 指代当前对象,哪个对象调用方法它指的就是哪个对象
只能用在方法中,方法中访问成员变量之前默认有个this.
this的用法:
-
this.成员变量名------------访问成员变量
-
当成员变量和局部变量同名时,若想访问成员变量,则this不能省略
-
this.方法名()----------------调用方法(可以省略,没有什么情况下是不能省略)
-
this()--------------------------调用构造方法
null: 表示空,没有指向任何对象。 若引用的值为null,则该引用不能进行任何点操作了,若操作则发生NullPointerException空指针异常。
引用类型数组:
- 给引用类型数组的元素赋值,需要new一下
- 若想访问对象的属性或调用方法,需要通过数组元素去打点
//注意:对于引用数组而言,必须给所有元素都赋值,否则访问时会发生空指针异常
Student[] stus = new Student[3]; //创建Student数组对象
stus[0] = new Student("zhangsan",25,"LF"); //创建Student对象
stus[1] = new Student("lisi",24,"JMS");
stus[2] = new Student("wangwu",26,"SD");
System.out.println(stus[0].name); //输出第1个学生的名字
stus[1].age = 28; //修改第2个学生的年龄为28
stus[2].sayHi(); //第3个学生跟大家问好
for(int i=0;i<stus.length;i++){ //遍历学生数组
System.out.println(stus[i].name); //输出每个学生的名字
stus[i].sayHi(); //每个学生跟大家问好
}
继承:
-
作用:代码复用
-
通过extends来实现继承
-
超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
-
派生类既可以访问派生类的,也能访问超类的,但超类不能访问派生类的
-
一个超类可以有多个派生类,一个派生类只能继承一个超类,即单一继承
-
具有传递性
-
java规定:构造派生类之前必须先构造超类
-
在派生类的构造方法中,若没有调用超类构造方法,则默认super()调用超类无参构造方法
public class SuperDemo { public static void main(String[] args) { Boo o = new Boo(); } } class Aoo{ Aoo(){ System.out.println("超类构造方法"); } } class Boo extends Aoo{ Boo(){ super(); //默认的,调用超类的无参构造方法 System.out.println("派生类构造方法"); } }
-
在派生类的构造方法中,若自己调用了超类构造方法,则不再默认提供
注意:super()调用超类构造方法,必须位于派生类构造方法的第一行
class Coo{ Coo(int a){ } } class Doo extends Coo{ Doo(){ super(5); //自己调用超类构造了,则不会再默认super() } /* //如下代码为默认的 Doo(){ super(); } */ }
-
super: 指代当前对象的超类对象
super的用法:
- super.成员变量名------------------------------访问超类的成员变量
- super.方法名()----------------------------------调用超类的方法
- super()--------------------------------------------调用超类的构造方法
向上造型:
-
复用性好
-
超类型的引用指向派生类的对象
-
能点出来什么,看引用的类型
多种角色能干的事都一样的时候,可以将多种角色统一造型到超类数组中,实现代码复用
方法的重写(override/overriding):
- 发生在父子类中,方法名相同,参数列表相同
- 重写方法被调用时,看对象的类型
- 重写需遵循"两同两小一大"原则:
- 两同:
- 方法名相同
- 参数列表相同
- 两小:
- 派生类方法的返回值类型小于或等于超类方法的
- void和基本类型时,必须相等
- 引用类型时,小于或等于
- 派生类方法抛出的异常小于或等于超类方法的
- 派生类方法的访问权限大于或等于超类方法的
- 派生类方法的返回值类型小于或等于超类方法的
- 两同:
重写与重载的区别:
- 重写(override):发生在父子类中,方法名相同,参数列表相同
- 重载(overload):发生在同一类中,方法名相同,参数列表不同
package: 声明包
- 作用:避免类的命名冲突
- 同包中的类不能同名,但不同包中的类可以同名
- 类的全称:包名.类名,常常有层次结构
- 建议:包名所有字母都小写
import: 导入类、引入类
- 同包中的类可以直接访问,但不同包中的类不参直接访问,若想访问:
- 先import导入类再访问类---------建议
- 类的全称-----------------------------太繁琐,不建议
注意:
顺序问题:package----import----class
import 包名.*; 表示导入了包中的所有类,但不建议,建议用哪个类导哪个类
------因为.*会影响性能
访问控制修饰符: 保护数据的安全
-
public:公开的,任何类
-
private:私有的,本类
-
protected:受保护的,本类、派生类、同包类
-
默认的:什么也不写,本类、同包类
注意:
-
java不建议默认权限
-
类的访问权限只能是public或默认的
类中成员的访问权限如上4种都可以
-
访问权限由大到小依次为:public–protected–默认的–private
package ooday05; //访问控制修饰符的演示 public class Aoo { public int a; //任何类 protected int b; //本类、派生类、同包类 int c; //本类、同包类 private int d; //本类 void show(){ a = 1; b = 2; c = 3; d = 4; } } class Boo{ //----------------演示private void show(){ Aoo o = new Aoo(); o.a = 1; o.b = 2; o.c = 3; //o.d = 4; //编译错误 } } package ooday05_vis; import ooday05.Aoo; public class Coo { //----------------演示同包的 void show(){ Aoo o = new Aoo(); o.a = 1; //o.b = 2; //编译错误 //o.c = 3; //编译错误 //o.d = 4; //编译错误 } } class Doo extends Aoo{ //跨包继承---------演示protected void show(){ a = 1; b = 2; //c = 3; //编译错误 //d = 4; //编译错误 } }
-
final: 最终的、不可改变的
- 修饰变量:变量不能被改变
//演示final修饰变量 class Eoo{ final int a = 5; void show(){ //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修饰
-
属于类,存储在方法区中,只有一份
-
常常通过类名点来访问
-
何时用:所有对象所共享的数据(图片、音频、视频等)
class Loo{ int a; static int b; Loo(){ a++; b++; } void show(){ System.out.println("a="+a+",b="+b); } } public class StaticDemo { public static void main(String[] args) { Loo o1 = new Loo(); o1.show(); Loo o2 = new Loo(); o2.show(); Loo o3 = new Loo(); o3.show(); System.out.println(Loo.b); //常常通过类名点来访问 } }
- 静态方法:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 静态方法中没有隐式this传递,所以不能直接访问实例成员
- 何时用:方法的操作与对象无关
//演示静态方法 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); //编译错误 System.out.println(Moo.b); } }
//演示静态方法何时用
class Noo{
int a; //实例变量----是属于对象的,描述对象的属性
//在show()中需要访问对象的属性a,说明此方法与对象有关,不能设计为静态方法
void show(){
System.out.println(a);
}
//在plus()中并没有访问对象的属性或行为,说明此方法与对象无关,可以设计为静态方法
static int plus(int num1,int num2){
int num = num1+num2;
return num;
}
}public class StaticDemo {
public static void main(String[] args) {
Moo.test(); //常常通过类名点来访问
}
} - 静态方法:
-
-
静态块:
- 由static修饰
- 属于类,在类被加载期间自动执行,因为一个类只被加载一次,所以静态块也只执行一次
- 何时用:加载/初始化静态资源(图片、音频、视频等)
//演示静态块 class Poo{ static{ System.out.println("静态块"); } Poo(){ System.out.println("构造方法"); } } public class StaticDemo { public static void main(String[] args) { Poo o4 = new Poo(); Poo o5 = new Poo(); Poo o6 = new Poo(); } } ```
static final常量: 应用率高
- 必须声明同时初始化
- 常常由类名点来访问,不能被改变
- 建议:常量所有字母都大写,多个单词用_分隔
- 编译器在编译时会将常量直接替换为具体的值,效率高
- 何时用:数据永远不变,并且经常使用
package ooday06;
//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.14159;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
抽象方法:
- 由abstract修饰
- 只有方法的定义,没有具体的实现(没有{})
抽象类:
- 由abstract修饰
- 包含抽象方法的类必须是抽象类
- 抽象类不能被实例化
- 抽象类是需要被继承的,派生类:
- 重写抽象方法(变不完整为完整)-----------一般做法
- 也声明为抽象类-------------------------------一般不这么做
- 抽象类的意义:
- 封装共有的属性和行为--------------------代码复用
- 为所有派生类提供统一的类型-----------向上造型(代码复用)
- 可以包含抽象方法,为所有派生类提供统一的入口(造型之后能点出来),同时可以达到强制必须重写的目的(相当于制定一个规则)