目录
4.构造方法:构造函数、构造器、构建器----复用给成员变量赋初值的代码
11.方法的重写(override/overriding):
1.方法重载(overload/overloading):
发生在同一类中,方法名称相同,参数列表不同
编译器在编译时会根据方法的签名自动绑定方法
2.类:是一种引用数据类型
引用
数据类型 引用类型变量 指向 对象
Student zs = new Student();//创建一个Student型的引用zs,指向了一个学生对象
3.默认值规则:
byte,short,int,long,char----------------0
float,double----------------------------0.0
boolean---------------------------------false
引用类型---------------------------------null
方法的签名:方法名+参数列表
4.构造方法:构造函数、构造器、构建器----复用给成员变量赋初值的代码
作用:给成员变量赋初始值
语法:与类同名,没有返回类型(连void都没有)
调用:在创建(new)对象时被自动调用
若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了构造方法,则不再默认提供
构造方法可以重载
5.this的用法
指代当前对象,哪个对象调用方法它指的就是哪个对象;只能用在方法中,方法中访问成员变量之前默认有个this
this.成员变量名----------访问成员变量
注:当成员变量与局部变量同名时,若想访问成员变量,则this不能省
this.方法名()----------调用方法(一般不这么写)
this()--------------------调用构造方法(一般很少用)
6.null:表示空,没有指向任何对象
如引用的值为null,则该引用不能再进行任何操作了,若操作则发生NullPointerException空指针异常
注:1.java规定:成员变量和局部变量是可以同名的,使用的时候默认采取就近原则
2.基本类型变量中存储的就是具体的数,引用类型变量中存储的是对应对象的地址
3.成员变量:写在类中,方法外,在整个类中好使
局部变量:写在方法中,当前方法中使用
7.引用类数组:
引用类型数组和基本类型数组的区别:
区别1:给引用类型数组的元素赋值时,需要new个对象
区别2:若想访问引用类型数组元素的数据,需要通过数组元素去打点
8.继承:
作用:代码复用
继承一定要符合is(是)的关系,通过extends来实现继承
超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
派生类可以访问派生类的也可以访问超类的,但超类不能访问派生类的
一个超类可以有多个派生类,但一个派生类只能有一个超类---------单一继承
具有传递性
java规定:构造派生类之前必须构造超类
在派生类构造方法中自己没有调用超类构造方法,则默认super()调用超类无参构造方法
在派生类构造方法中若自己调用了超类构造方法,则不再默认提供
注:super()调用超类构造方法,必须位于派生类构造方法的第一行
9.super:指代当前对象的超类对象
super的用法:
super.成员变量名----------访问超类的成员变量
super.方法名()--------------调用超类的方法
super()------------------------调用超类的构造方法
注:当超类的成员变量与派生类的成员变量同名时,若不写super或this,则默认就近原则(默认访问的是派生类的成员变量)。若想访问超类的成员变量,必须用super.成员变量名
10.向上造型(多态):
超类型的引用指向了派生类的对象
1.多种角色干的事都一样的时候,可以将那多种角色统一造型到超类数组中,实现代码复用
2.将超类作为参数或返回值类型,传递派生类对象或返回派生类对象,也是在复用代码
public class ExtendsDemo {
public static void main(String[] args) {
Aoo o1 = new Aoo();
o1.a = 1;
o1.show();
//o1.b = 2; //编译错误
//o1.test(); //编译错误,超类不能访问派生类的
Boo o2 = new Boo();
o2.b = 1;
o2.test();
o2.a = 2; //正确
o2.show(); //正确,派生类可以访问超类的
//能点出来什么,看引用的类型------------------这是规定,记住就OK了
Aoo o3 = new Boo(); //向上造型
o3.a = 1;
o3.show();
//o3.b = 2; //编译错误
//o3.test(); //编译错误,能点出来什么,看引用的类型
}
}
class Aoo{
int a;
void show(){
}
}
class Boo extends Aoo{
int b;
void test(){
}
}
11.方法的重写(override/overriding):
发生在父子类中,方法名相同,参数列表相同
重写方法被调用时,看对象的类型
重写的原则(两同两小一大):
两同:方法名相同,参数列表相同
两小:派生类方法的返回值类型小于或等于超类方法的返回类型
void和基本类型时,必须相等
引用类型时,小于或等于
派生类方法抛出的异常小于或等于超类方法的
一大:派生类方法的访问权限大于或等于超类方法的
public class OverrideDemo {
public static void main(String[] args) {
}
}
//超类大,派生类小
class Aoo{
void show(){}
double test(){ return 0.0; }
Boo say(){ return null; }
Aoo sayHi(){ return null; }
}
class Boo {
//int show(){ return 1; } //编译错误,void时必须相等
//int test(){ return 0; } //编译错误,基本类型时必须相等
//Aoo say(){ return null; } //编译错误,引用类型时必须小于或等于
Boo sayHi(){ return null; } //正确,Boo小于Aoo
}
12.package和import
package:声明包
作用:避免类的命名冲突
同包中的类不能同名,但是不同包中的类可以同名
类的全称:包名.类名
建议:包名所有字母都小写,并且常常有层次结构
import:导入类
同包中的类可以直接访问,但不同包中的类不能直接访问,若想访问:
先import导入类,再访问类------建议
类的全称------------------------------繁琐
13.访问控制修饰符
public:公开的,任何类
private:私有的,本类
protected:受保护的,本类,派生类,同包类
默认的:本类,同包类--------------------------java不建议默认权限
访问控制修饰符的访问权限由低到高依次为:private<默认的<protected<public
package ooday04;
//演示访问控制修饰符
public class Coo {
public int a; //任何类
protected int b; //本类、派生类、同包类
int c; //本类、同包类
private int d; //本类
void show(){
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Doo{ //-------------------演示private
void show(){
Coo o = new Coo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4; //编译错误
}
}
package ooday04_vis;
import ooday04.Coo;
public class Eoo { //-----------------演示同包的
void show(){
Coo o = new Coo();
o.a = 1;
//o.b = 2; //编译错误
//o.c = 3; //编译错误
//o.d = 4; //编译错误
}
}
class Foo extends Coo{ //跨包继承-----------演示protected
void show(){
a = 1;
b = 2;
//c = 3; //编译错误
//d = 4; //编译错误
}
}
14.static:静态的
静态变量:
由static修饰
属于类,存储在方法区中,只有一份
常常通过类名点来访问
何时用:所有对象所共享的数据(图片,音频,视频等)
package ooday04;
//static的演示
public class StaticDemo {
public static void main(String[] args) {
Foo o1 = new Foo();
o1.show();
Foo o2 = new Foo();
o2.show();
Foo o3 = new Foo();
o3.show();
System.out.println(Foo.b); //常常通过类名点来访问
}
}
//演示静态变量
class Foo{
int a; //实例变量
static int b; //静态变量
Foo(){
a++; //今天晚上的晚课,暂停一次
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
}
静态方法:
由static修饰
属于类,存储在方法区中,只有一份
常常通过类名点来访问
静态方法中没有隐士this传递,所以不能直接访问实例成员
何时用:方法的操作与对象无关
package ooday04;
//static的演示
public class StaticDemo {
public static void main(String[] args) {
int num = Hoo.plus(5,6); //常常通过类名点来访问
}
}
//演示静态方法何时用
class Hoo{
int a; //描述的是对象的属性
//show()中需要访问对象的属性,说明show()方法与对象有关,所以不能设计为静态方法
void show(){
System.out.println(a);
}
//plus()中不需要访问对象的属性,说明plus()方法与对象无关,所以可以设计为静态方法
static int plus(int num1,int num2){
int num = num1+num2;
return num;
}
}
//演示静态方法
class Goo{
int a; //实例变量(通过对象来访问)
static int b; //静态变量(通过类名来访问)
void show(){ //有隐式this
System.out.println(this.a);
System.out.println(Goo.b);
}
static void test(){ //没有隐式this
//静态方法中没有隐式this传递
//没有this就意味着没有对象
//而实例变量a必须通过对象来访问
//所以如下语句发生编译错误
//System.out.println(a); //编译错误
System.out.println(Goo.b);
}
}
静态块:
由static修饰
属于类,在类被加载期间自动执行,一个类只被加载一次,所以静态块只执行一次
何时用:初始化/加载静态资源(图片、图片、视频)
package ooday04;
//static的演示
public class StaticDemo {
public static void main(String[] args) {
Ioo o4 = new Ioo();
Ioo o5 = new Ioo();
Ioo o6 = new Ioo();
}
}
//演示静态块
class Ioo{
static {
System.out.println("静态块");
}
Ioo(){
System.out.println("构造方法");
}
}
数据(成员变量)私有化(private),行为(方法)大部分都公开化(public)
成员变量分两种:
实例变量:没有static修饰,属于对象的,存储在堆中,有几个对象就有几分,通过引用名(对象)打点来访问
静态变量:有static修饰,属于类,存储在方法区中,只有一份,通过类名打点来访问
内存管理:由JVM管理的
堆:new出来的对象(包括实例变量、数组的元素)
栈:局部变量(包括方法的参数)
方法区:.class字节码文件(包括静态变量、所有方法)
15.final:最终的、不可改变的
修饰变量:变量不能改变
修饰方法:方法不能被重写
修饰类:类不能被继承
static final常量:
必须声明同时初始化
常常由所有类名来访问,不能被改变
建议:常量名所有字母都大写,多个单词用下划线(_)分隔
编译器在编译时会将常量直接替换为具体的数,效率高
何时用:程序运行过程中数据永远不变,并且经常使用
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Hoo.PI); //常常由类名点来访问
//Hoo.PI = 3.1415926; //编译错误,常量不能被改变
//1)加载Ioo.class到方法区中
//2)静态变量num一并存储到方法区中
//3)到方法区中获取num的值并输出
System.out.println(Ioo.num);
//编译器在编译时会将常量直接替换为具体的数,效率高
//相当于System.out.println(5);
System.out.println(Ioo.COUNT);
}
}
class Ioo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
class Hoo{
public static final double PI = 3.1415926;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
16.抽象方法:
由abstract修饰
只有方法的定义,没有具体的实现(连{}都没有)
17.抽象类:
由abstract修饰
包含抽象方法的类必须是抽象类
抽象类不能被实例化(new对象)
抽象类是需要被继承的,派生类
重写所有抽象方法
也设计为抽象类
抽象类的意义:
封装共有的属性和行为
为所有派生类提供统一的类型----向上造型
可以包含抽象方法,为所有派生类提供统一的入口,同时达到强制重写的目的
抽象方法/抽象类的疑问:
抽象方法的意义:
保证当发生向上造型时,通过超类的引用能点出那个方法来
既然抽象方法的意义是保证能点出来,为什么不设计为普通方法呢?
设计为普通方法,意味着派生类可以重写也可以不重写,但设计为抽象方法,
则可以强制派生类必须重写,以达到统一的目的
含抽象方法的类一定是抽象类,不含抽象方法的类也可以是抽象类,
abstract和final不能同时修饰一个类
18.成员内部类
类中套类,外面的称为外部类,里面的称为内部类
内部类通常只服务于外部类,对外不具备可见性
内部类对象通常只在外部类中创建
内部类中可以直接访问外部类的成员(包括私有的)
内部类中有一个隐式的引用指向了创建它的外部类对象------外部类名.this
何时用:有一个类A,只能被另一个类B使用,并且还想访问类B的成员,可以设计为成员内部类
隐式的引用:
this:指代当前对象
super:指代当前对象的超类对象
外部类名.this:指代当前对象的外部类对象
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,Baby类对外不可见
}
}
class Mama{ //外部类
private String name;
void create(){
Baby b = new Baby(); //正确
}
class Baby{ //内部类
void showName(){
System.out.println(name); //简写
System.out.println(Mama.this.name); //完整写法--Mama.this指Mama对象
//System.out.println(this.name); //编译错误,this指Baby对象
}
}
}
19.匿名内部类
何时用:若想创建一个类(派生类)的对象,并且对象只被创建一次,可以设计为匿名内部类
匿名内部类中不能修改外面局部变量的值,因为在此处该变量默认为final
内部类有独立的.class字节码文件吗?-------有
方法的调用:
同一类中的方法,可以直接写方法名调用
不同类中的方法:
若为实例方法(没有static), 则通过引用变量调用
若为静态方法(有static),则通过类名调用
public class NstInnerClassDemo {
public static void main(String[] args) {
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1,向上造型为Aoo类型
// ---new Aoo(){}是在创建Aoo的派生类的对象
//3)大括号中的为派生类的类体
Aoo o1 = new Aoo(){
};
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2,向上造型为Aoo类型
// ---new Aoo(){}是在创建Aoo的派生类的对象
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){
};
int num = 5;
num = 55;
//1)创建了Boo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o3,向上造型为Boo类型
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){
System.out.println("showshow");
//num = 66; //编译错误,num在此处默认为final的,所以不能修改
}
};
o3.show();
}
}
abstract class Boo{
abstract void show();
}
abstract class Aoo{
}
20.接口
是一种引用数据类型
由interface定义
只能包含常量和抽象方法(数据默认都是常量,方法默认都是抽象的),权限只能是public
interface Inter{ //接口中成员的访问权限只能是public(默认也是public)
public static final int NUM = 5;
public abstract void show();
int COUNT = 6; //默认public static final
void test(); //默认public abstract
//int number; //编译错误,常量必须声明同时初始化
//void say(){} //编译错误,抽象方法不能方法体
}
接口不能被实例化(new对象)
接口是需要被实现/继承的,实现类/派生类:必须重写所有抽象方法
interface Inter1{
void show();
void test();
}
class Aoo implements Inter1{
public void show(){} //重写接口中的抽象方法时,必须加public
public void test(){}
}
一个类可以实现多个接口,用逗号分隔。若又继承又实现时,应先继承后实现
interface Inter2{
void show();
}
interface Inter3{
void test();
}
abstract class Boo{
abstract void say();
}
class Coo extends Boo implements Inter2,Inter3{
public void show(){}
public void test(){}
void say(){}
}
接口可以继承接口
interface Inter4{
void show();
}
interface Inter5 extends Inter4{
void test();
}
class Doo implements Inter5{
public void test(){}
public void show(){}
}
public class InterfaceDemo {
public static void main(String[] args) {
//Inter5 o1 = new Inter5(); //编译错误,接口不能被实例化
Inter5 o2 = new Doo(); //向上造型
Inter4 o3 = new Doo(); //向上造型
}
}
类接口关系:
类与类--------------------------继承extends
接口和接口--------------------继承extends
类和接口-----------------------实现implements
21.多态
表现:同一个对象被造型为不同的类型时,有不同的功能----------所有对象都是多态的
同一类型的引用指向不同的对象时,有不同的实现-----------所有抽象方法都是多态的
向上造型/自动类型转换:
超类型的引用指向派生类的对象
能点出来什么,看引用的类型
能向上造型成为的类型有:超类+所有实现的接口
向下转型/强制类型转换,成功的条件只有如下两种:
引用所指向的对象,就是该类型
引用所指向的对象,实现了该接口或继承了该类
强转时若不符合如上条件,则发生ClassCastException类型转换异常
建议:在强转之前先通过instanceof判断引用指向的对象是否是该类型
注意:1.instanceof返回boolean结果,它为true的条件与强转成功的条件是一样的
2.何时需要强转:若想访问的变量/方法在超类中没有,则需要强转
public class MultiTypeDemo {
public static void main(String[] args) {
//条件1: 引用所指向的对象,就是该类型
//条件2: 引用所指向的对象,实现了该接口或继承了该类
Aoo o = new Boo(); //向上造型
Boo o1 = (Boo)o; //引用o所指向的对象,就是Boo类型-------符合条件1
Inter o2 = (Inter)o; //引用o所指向的对象,实现了Inter接口---符合条件2
//Coo o3 = (Coo)o; //运行时会发生类型转换异常
if(o instanceof Coo){ //false
Coo o4 = (Coo)o;
}else{
System.out.println("o不是Coo类型");
}
//System.out.println(o instanceof Boo); //true
//System.out.println(o instanceof Inter); //true
//System.out.println(o instanceof Coo); //false
}
}
interface Inter{ } //大
class Aoo{ } //大
class Boo extends Aoo implements Inter{ } //小
class Coo extends Aoo{ } //小
22.内存管理:由JVM管理的
堆:存储new出来的对象(包括实例变量、数组的元素)
垃圾:没有任何引用所指向的对象
垃圾回收器(GC)不定时到内存堆中清扫垃圾,回收过程是透明的,不一定一发现垃圾
就立刻回收,通过调用System.gc()可以建议JVM尽快调度GC来回收。
实例变量的生命周期:创建对象时存储在堆中,对象被回收时一并回收
内存泄漏:不再使用的对象还没有被及时的回收,严重的泄露会导致系统的崩溃
建议:不再使用的对象应及时将引用设置为null
栈|:存储正在调用的方法中的局部变量(包括方法的参数)
调用方法时,会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(方法的
参数),方法调用结束时,栈帧被自动清除,局部变量一并被清除
局部变量的生命周期:调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
方法区:存储.class字节码文件(包括静态变量、所有方法)
方法只有一份,通过this来区分具体的调用对象
23.面向对象三大特征总结:
封装:类:封装的是对象的属性和行为
方法:封装的是具体的业务逻辑功能实现
访问控制修饰符:封装的是具体的访问权限,隐藏数据,暴露功能
继承:作用:代码复用
超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的属性和行为
派生类:派生类所特有的属性和行为
特点:单一继承、多接口实现、具有传递性
多态:多种形态
所有对象都是多态的-----------------------------------通过向上造型来体现
所有抽象方法都是多态的-----------------------------通过方法的重写来体现
向上造型、向下转型(强制类型转换)