JAVA基础复习-基础概念

重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了。

如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系。

重写:父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。

Java中的内存分配以及栈和堆的区别


A:栈(掌握) 
存储局部变量
B:堆(掌握) 
存储new出来的数组或对象
C:方法区 
面向对象部分讲解
D:本地方法区 
和系统相关
E:寄存器 
给CPU使用


Java中的参数传递问题


基本数据类型的值传递,不改变原值,因为调用后就会弹栈,局部变量随之消失
引用数据类型的值传递,改变原值,因为即使方法弹栈,但是堆内存数组对象还在,可以通过地址继续访问

Java中到底是传值还是传址?

1,既是传值,也是传地址,基本数据类型传递的值,引用数据类型传递的地址

2,java中只有传值,因为地址值也是值(出去面试都说这种,支持者是高司令(java之父))

成员变量和局部变量的区别(掌握)


A:在类中的位置不同 
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同 
成员变量:在堆内存(成员变量属于对象,对象进堆内存)
局部变量:在栈内存(局部变量属于方法,方法进栈内存)
C:生命周期不同 
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同

成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:

局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
基本数据类型变量包括哪些:byte,short,int,long,float,double,boolean,char
引用数据类型变量包括哪些:数组,类,接口,枚举
面向对象
Java面向对象思想和三大特性:java面向对象思想和三大特性 - 黑马飞的博客 - 博客频道 - CSDN.NET

静态变量和成员变量的区别(掌握)
静态变量也叫类变量 成员变量也叫对象变量
A:所属不同 
静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
B:内存中位置不同 
静态变量存储于方法区的静态区
成员变量存储于堆内存
C:内存出现时间不同 
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
D:调用不同 
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
static的注意事项(掌握)
A:static的注意事项 
a:在静态方法中是没有this关键字的 
如何理解呢? 
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
b:静态方法只能访问静态的成员变量和静态的成员方法 
静态方法: 
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法: 
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记: 
静态只能访问静态。
代码块(了解)
A:代码块概述 
在Java中,使用{}括起来的代码被称为代码块。
B:代码块分类 
根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
C:常见代码块的应用 
a:局部代码块 
在方法中出现;限定变量生命周期,及早释放,提高内存利用率
b:构造代码块 (初始化块) 
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
c:静态代码块 
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
一般用于加载驱动
继承
A:继承的注意事项 
a:子类只能继承父类所有非私有的成员(成员方法和成员变量)
b:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
c:不要为了部分功能而去继承
this和super的区别和应用(掌握)
A:this和super都代表什么 
this:代表当前对象的引用,谁来调用我,我就代表谁
super:代表当前对象父类的引用
B:this和super的使用区别 
a:调用成员变量 
this.成员变量 调用本类的成员变量,也可以调用父类的成员变量
super.成员变量 调用父类的成员变量
b:调用构造方法 
this(…) 调用本类的构造方法
super(…) 调用父类的构造方法
c:调用成员方法 
this.成员方法 调用本类的成员方法,也可以调用父类的方法
super.成员方法 调用父类的成员方法
继承中构造方法的关系(掌握)
A:案例演示 
子类中所有的构造方法默认都会访问父类中空参数的构造方法
B:为什么呢?

因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。

其实:

每一个构造方法的第一条语句默认都是:super() Object类最顶层的父类。
方法重写的注意事项(掌握)
A:方法重写注意事项

a:父类中私有方法不能被重写 
因为父类私有方法子类根本就无法继承
b:子类重写父类方法时,访问权限不能更低 
最好就一致
c:父类静态方法,子类也必须通过静态方法进行重写

其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态)
子类重写父类方法的时候,最好声明一模一样。

方法重写的面试题(掌握)
A:方法重写的面试题

Override(重写)和Overload(重载)的区别?Overload能改变返回值类型吗?
overload可以改变返回值类型,只看参数列表
方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值类型有关,返回值是一致(或者是子父类)的

方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值类型无关。

子类对象调用方法的时候:

先找子类本身,再找父类。(就近原则)
final关键字修饰类,方法以及变量的特点(掌握)
A:final修饰特点 
修饰类,类不能被继承
修饰变量,变量就变成了常量,只能被赋值一次
修饰方法,方法不能被重写
B:案例演示 
final修饰特点 
基本类型,是值不能被改变
引用类型,是地址值不能被改变,对象中的属性可以改变
多态
A 概述:事物存在的多种状态
B 多态前提

a:要有继承关系
b:要有方法重写
c:要有父类引用指向子类对象,比如Animal an=new Cat();//Cat类继承Animal类
C 访问成员变量和成员方法的区别

a 成员变量(无论是否静态):编译看左边(父类),运行看左边(父类),就是父类跟子类都有一个 int num,但多态中的话, 
Father f=new Son();//Son继承Father,f.num是访问Father类里面的num
b 成员方法:编译看左边(父类),运行看右边(子类),就是子类Son重写了父类Father的方法show,父类 Father就会调用 show()方法调用子类的方法show(),这个也叫动态绑定
c 静态方法:编译看左边(父类),运行看左边(父类),其实这种相当于类名.方法 
总结:只有非静态的成员方法才会动态绑定(编译看左边,运行看右边),像成员变量以及静态方法不会动态绑定 (编译看左边,运行看左边)
D 向上转型和向下转型

a 向上转型:父类引用指向子类对象,就是向上转型,比如Father father=new Son();
b 向下转型:前提必须有向上转型,比如Son s=(Son)father;//前提有Father father=new Son();
抽象类
abstract不可以和static,final,private等共用 
* A 抽象类的成员特点 
* a 成员变量:可以是变量也可以是常量,abstract不可以修饰成员变量 
* b 构造方法:有(每个类都有一个默认的构造方法,无论类是否抽象) 
* c 成员方法:可以是抽象方法(强制要求子类做的事情),也可以是非抽象方法的(子类继承的事情,提高代码的 复用性,可以重写)

B 面试题:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义呢? 
可以,这样做的目的只有一个:那就是不让其他类创建本类对象,交给子类完成
接口的成员特定
A 成员变量:只能是常量,并且是静态的以及公共的. 
* 默认修饰符:public static final 
* 建议:自己手动给出
B 构造方法:接口没有构造方法
C 成员方法:只能是抽象方法 
* 默认修饰符:public abstract 
* 建议:自己手动给出
类于类,类与接口,接口与接口的关系
A 类于类: 
继承关系,只能单继承,可以多层继承
B 类与接口: 
实现关系:可以单实现,也可以多实现
并且还可以在继承一个类的同时实现多个接口
C 接口与接口(使用extends): 
继承关系,可以单继承,也可以多继承
四种权限修饰符的测试(掌握)


内部类访问特点
a:内部类可以直接访问外部类的成员,包括私有。内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用外部类名.this
b:外部类要访问内部类的成员,必须创建对象。

外部类名.内部类名 对象名 = 外部类对象.内部类对象;(例如:Outer.Inner inner =new Outer(). new Inner();)

d:成员内部类被静态修饰后的访问方式是:

外部类名.内部类名 对象名 = 外部类名.内部类对象;例如(Outer.Inner inner =new Outer. Inner();),但注意new是属于Inner()那里的
(局部内部类访问局部变量的问题)(掌握)
局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么? 
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用

但是jdk1.8取消了这个事情,所以我认为这是个bug

匿名内部类
A:前提:存在一个类或者接口 
这里的类可以是具体类也可以是抽象类。
B:本质是什么呢?

是一个继承了该类或者实现了该接口的子类匿名对象。其实我个人感觉就是一个多态(向上转型),接着使用通过动态调用子类实现的方法
C:注意:

匿名内部类只针对重写一个方法时候使用
匿名内部类是不能向下转型的,因为没有子类类名
D:问题讨论

内部类(不是静态的)是否可以在外部类静态方法(外部类指的是包含内部类的那个类)中创建实例呢?如果不行,该如何修改才可以呢? 
答: 
1.内部类不可以在静态方法中创建实例或者调用内部类的静态方法,这里我个人认为应该把内部类看做一个属性(非静态的成员变量),非静态的成员变量是不可以在静态类中使用的; 
2.如果你想使用,就需要在内部类前加上静态static,这样其实相当于Outer类跟内部类Inter是并行关系,以前内部类没有static的时候,内部类就可以看做是Outer的是一个非静态成员变量,不过内部类现在有了static,内部类Inter跟Outer是并行关系,不再是以前仅仅的从属关系了,代码如下: 
PS:一句话讲完:非静态内部类Inter看做Outer类中的一个属性(非静态的成员变量,属于中国跟广东省的关系),但加静态内部类Inter跟Outer类就可以看成是中国跟香港的关系了,享有高度自治的特权) 
3.非静态的内部类也不可以有静态方法(这个跟我们平时接触的类有点不同,因为我们平时接触的都是外部类)

    public static void main(String[] args) {

        new Outer.Inter().interPrint();//成了静态内部类之后,我就可以像香港一样,有自己的对外贸易规则
        Outer.Inter.sinterPrint();//sinterPrint是静态方法,类名可以直接调用
        new Outer().outerPrint();

    }
}

class Outer {
   //因为Inter已经成为了静态内部类,所以outPrint方法static不显得重要了(核心:内部类就相当于一个类中的一个特殊属性)
    public static void outerPrint() {

        Inter inter = new Inter();
        inter.interPrint();
    }

    static class Inter {
        public void interPrint() {
            System.out.println("我是内部类");
        }

        public static void sinterPrint() {
            System.out.println("我是匿名内部类的静态方法");
        }
    }
}
 

匿名对象使用场景

1当对方法只进行一次调用的时候,可以使用匿名对象。

2当对象对成员进行多次调用时,不能使用匿名对象。必须给对象起名字。

 

类中怎么没有定义主函数呢?

注意:主函数的存在,仅为该类是否需要独立运行,如果不需要,主函数是不用定义的。

主函数的解释:保证所在类的独立运行,是程序的入口,被jvm调用。

 

成员变量和局部变量的区别:

1:成员变量直接定义在类中。

局部变量定义在方法中,参数上,语句中。

2:成员变量在这个类中有效。

局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域。

3:成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。

局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放。

 

构造函数:用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种。

特点

1该函数的名称和所在类的名称相同。

2不需要定义返回值类型。

3该函数没有具体的返回值。

记住:所有对象创建时,都需要初始化才可以使用。

 

注意事项:一个类在定义时,如果没有定义过构造函数,那么该类中会自动生成一个空参数的构造函数,为了方便该类创建对象,完成初始化。如果在类中自定义了构造函数,那么默认的构造函数就没有了。

 

一个类中,可以有多个构造函数,因为它们的函数名称都相同,所以只能通过参数列表来区分。所以,一个类中如果出现多个构造函数。它们的存在是以重载体现的。

 

构造代码块和构造函数有什么区别?

构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用一个代码块。只要对象一建立。就会调用这个代码块。

构造函数:是给与之对应的对象进行初始化。它具有针对性。

  1. 执行顺序:(优先级从高到低。)静态代码块>mian方法>构造代码块>构造方法。其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。

  2. 静态代码块的作用:比如我们在调用C语言的动态库时会可把.so文件放在此处。 

  3. 构造代码块的功能:(可以把不同构造方法中相同的共性的东西写在它里面)。例如:比如不论任何机型的电脑都有开机这个功能,此时我们就可以把这个功能定义在构造代码块内。

 

Person p = new Person();

创建一个对象都在内存中做了什么事情?

1先将硬盘上指定位置的Person.class文件加载进内存。

2执行main方法时,在栈内存中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量p。

3在堆内存中开辟一个实体空间,分配了一个内存首地址值。new

4在该实体空间中进行属性的空间分配,并进行了默认初始化。

5对空间中的属性进行显示初始化。

6进行实体的构造代码块初始化。

7调用该实体对应的构造函数,进行构造函数初始化。()

8将首地址赋值给p ,p变量就引用了该实体。(指向了该对象)

 

 

封 装(面向对象特征之一):是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:将变化隔离;便于使用;提高重用性;安全性。

封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。

 

this:代表对象。就是所在函数所属对象的引用。

this到底代表什么呢?哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用。

开发时,什么时候使用this呢?

在定义功能时,如果该功能内部使用到了调用该功能的对象,这时就用this来表示这个对象。

 

this 还可以用于构造函数间的调用。

调用格式:this(实际参数);

this对象后面跟上 . 调用的是成员属性和成员方法(一般方法);

this对象后面跟上 () 调用的是本类中的对应参数的构造函数。

 

注意:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初始化动作一定要执行。否则编译失败。

 

static:★★★ 关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。

特点:

1、static变量

 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:

 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。

 对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

2、静态方法

 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!

 因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

3、static代码块

 static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。

4、static和final一块用表示什么

static final用来修饰成员变量和成员方法,可简单理解为"全局常量"!

对于变量,表示一旦给值就不可修改,并且通过类名可以访问。

对于方法,表示不可覆盖,并且可以通过类名直接访问。

 

备注:

1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。

2,静态方法只能访问静态成员,不可以访问非静态成员。

(这句话是针对同一个类环境下的,比如说,一个类有多个成员(属性,方法,字段),静态方法A,那么可以访问同类名下其他静态成员,你如果访问非静态成员就不行)

因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。

3,静态方法中不能使用this,super关键字。

因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。

4,主函数是静态的。

 

成员变量和静态变量的区别:

1,成员变量所属于对象。所以也称为实例变量。

静态变量所属于类。所以也称为类变量。

2,成员变量存在于堆内存中。

静态变量存在于方法区中。

3,成员变量随着对象创建而存在。随着对象被回收而消失。

静态变量随着类的加载而存在。随着类的消失而消失。

4,成员变量只能被对象所调用 。

静态变量可以被对象调用,也可以被类名调用。

所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。

 

静态代码块:就是一个有静态关键字标示的一个代码块区域。定义在类中。

作用:可以完成类的初始化。静态代码块随着类的加载而执行,而且只执行一次(new 多个对象就只执行一次)。如果和主函数在同一类中,优先于主函数执行。

 

final

 根据程序上下文环境,Java关键字final有"这是无法改变的"或者"终态的"含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变、设计或效率。

final类不能被继承,没有子类,final类中的方法默认是final的。

final方法不能被子类的方法覆盖,但可以被继承。

final成员变量表示常量,只能被赋值一次,赋值后值不再改变。

final不能用于修饰构造方法。

注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。

1、final类

final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。

2、final方法

如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。

使用final方法的原因有二:

第一、把方法锁定,防止任何继承类修改它的意义和实现。

第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。

3、final变量(常量)

 用final修饰的成员变量表示常量,值一旦给定就无法改变!

 final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。

 从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。

 另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。

4、final参数

当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。

 

 

生成Java帮助文档:命令格式:javadoc –d 文件夹名 –auther –version *.java

/** //格式

*类描述

*@author 作者名

*@version 版本号

*/

/**

*方法描述

*@param 参数描述

*@return 返回值描述

*/

 

 

继 承(面向对象特征之一)

java中对于继承,java只支持单继承。java虽然不直接支持多继承,但是可实现多接口。

 

1:成员变量。

     当子父类中出现一样的属性时,子类类型的对象,调用该属性,值是子类的属性值。

     如果想要调用父类中的属性值,需要使用一个关键字:super

     This:代表是本类类型的对象引用。

     Super:代表是子类所属的父类中的内存空间引用。

     注意:子父类中通常是不会出现同名成员变量的,因为父类中只要定义了,子类就不用在定义了,直接继承过来用就可以了。

2:成员函数。

当子父类中出现了一模一样的方法时,建立子类对象会运行子类中的方法。好像父类中的方法被覆盖掉一样。所以这种情况,是函数的另一个特性:重写

3:构造函数。

发现子类构造函数运行时,先运行了父类的构造函数。为什么呢?

原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super();

super(): 表示父类的构造函数,并会调用于参数相对应的父类中的构造函数。而super():是在调用父类中空参数的构造函数。

为什么子类对象初始化时,都需要调用父类中的函数?(为什么要在子类构造函数的第一行加入这个super()?)

因为子类继承父类,会继承到父类中的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程

 

注意:子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();

如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。

如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。

 

问题:

super()和this()是否可以同时出现的构造函数中?

两个语句只能有一个定义在第一行,所以只能出现其中一个。

super()或者this():为什么一定要定义在第一行?

因为super()或者this()都是调用构造函数,构造函数用于初始化,所以初始化的动作要先完成。

 

在方法覆盖时,注意两点:

1:子类覆盖父类时,必须要保证,子类方法的权限必须大于等于父类方法权限可以实现继承。否则,编译失败。(举个例子,在父类中是public的方法,如果子类中将其降低访问权限为private,那么子类中重写以后的方法对于外部对象就不可访问了,这个就破坏了继承的含义)

2:覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)

 

继承的一个弊端:打破了封装性。对于一些类,或者类中功能,是需要被继承,或者复写的。

这时如何解决问题呢?介绍一个关键字,final

 

final特点:(详细解释见前面)

1:这个关键字是一个修饰符,可以修饰类,方法,变量。

2:被final修饰的类是一个最终类,不可以被继承。

3:被final修饰的方法是一个最终方法,不可以被覆盖。

4:被final修饰的变量是一个常量,只能赋值一次。

 

抽象类: abstract

抽象类的特点:

1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。

2:抽象方法只定义方法声明,并不定义方法实现。

3:抽象类不可以被创建对象(实例化)。

4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

 

抽象类的细节:

1:抽象类中是否有构造函数?有,用于给子类对象进行初始化。

2:抽象类中是否可以定义非抽象方法?

    可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。

3:抽象关键字abstract和哪些不可以共存?final ,    private , static

4:抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。

 

 

接 口:★★★★★

1:是用关键字interface定义的。

2:接口中包含的成员,最常见的有全局常量、抽象方法。

注意:接口中的成员都有固定的修饰符。

    成员变量:public static final

    成员方法:public abstract

interface Inter{

    public static final int x = 3;

    public abstract void show();

}

3:接口中有抽象方法,说明接口不可以实例化接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

4:类与类之间存在着继承关系,类与接口中间存在的是实现关系。

    继承用extends ;实现用implements ;

5:接口和类不一样的地方,就是,接口可以被多实现,这就是多继承改良后的结果。java将多继承机制通过多现实来体现。

6:一个类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了单继承的局限性。还可以将类进行功能的扩展。

7:其实java中是有多继承的。接口与接口之间存在着继承关系,接口可以多继承接口

java类是单继承的。classB Extends classA

java接口可以多继承。Interface3 Extends Interface0, Interface1, interface……

不允许类多重继承的主要原因是,如果A同时继承B和C,而b和c同时有一个D方法,A如何决定该继承那一个呢?

但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。

 

抽象类与接口:

抽象类:一般用于描述一个体系单元,将一组共性内容进行抽取,特点:可以在类中定义抽象内容让子类实现,可以定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容

接口:一般用于定义对象的扩展功能,是在继承之外还需这个对象具备的一些功能。

 

抽象类和接口的共性:都是不断向上抽取的结果。

 

抽象类和接口的区别:

1:抽象类只能被继承,而且只能单继承。

接口需要被实现,而且可以多实现。

2:抽象类中可以定义非抽象方法,子类可以直接继承使用。

接口中都是抽象方法,需要子类去实现。

3:抽象类使用的是 is a 关系。

接口使用的 like a 关系。

4:抽象类的成员修饰符可以自定义。

接口中的成员修饰符是固定的。全都是public的。

 

多 态★★★★★

多 态★★★★★(面向对象特征之一):函数本身就具备多态性,某一种事物有不同的具体的体现。

 

体现:父类引用或者接口的引用指向了自己的子类对象。//Animal a = new Cat();父类可以调用子类中覆写过的(父类中有的方法)

多态的好处:提高了程序的扩展性。继承的父类或接口一般是类库中的东西,(如果要修改某个方法的具体实现方式)只有通过子类去覆写要改变的某一个方法,这样在通过将父类的应用指向子类的实例去调用覆写过的方法就行了!

多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性)

多态的前提:

    1:必须要有关系,比如继承、或者实现。

    2:通常会有覆盖操作。

 

如果想用子类对象的特有方法,如何判断对象是哪个具体的子类类型呢?

可以可以通过一个关键字 instanceof ;//判断对象是否实现了指定的接口或继承了指定的类

 

格式:<对象 instanceof 类型> ,判断一个对象是否所属于指定的类型。

Student instanceof Person = true;//student继承了person类

 

-------------------------------------------------------------------------------------java.lang.Object

Object:所有类的直接或者间接父类,Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,最终就抽取到了一个最顶层的类中的,该类中定义的就是所有对象都具备的功能。

 

具体方法:

  1. boolean equals(Object obj):用于比较两个对象是否相等,其实内部比较的就是两个对象地址。

2,String toString():将对象变成字符串;默认返回的格式:类名@哈希值 = getClass().getName() + '@' + Integer.toHexString(hashCode())

    为了对象对应的字符串内容有意义,可以通过复写,建立该类对象自己特有的字符串表现形式。

    public String toString(){

        return "person : "+age;

    }

3,Class getClass():获取任意对象运行时的所属字节码文件对象。

4,int hashCode():返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。将该对象的内部地址转换成一个整数来实现的。

 

通常equals,toString,hashCode,在应用中都会被复写,建立具体对象的特有的内容。

-------------------------------------------------------------------------------------

 

内部类:如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,直接将A类定义在B类中。就可以了。A类就称为内部类。内部类可以直接访问外部类中的成员。而外部类想要访问内部类,必须要建立内部类的对象。

-----------------------------------------------------

class Outer{

    int num = 4;    

    class Inner {

        void show(){

            System.out.println("inner show run "+num);

        }

    }

    public void method(){

        Inner in = new Inner();//创建内部类的对象。

        in.show();//调用内部类的方法。 //内部类直接访问外部类成员,用自己的实例对象;

    }                                        //外部类访问内部类要定义内部类的对象;

}

-------------------------------------------------------

当内部类定义在外部类中的成员位置上,可以使用一些成员修饰符修饰 private、static。

1:默认修饰符。

直接访问内部类格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;

Outer.Inner in = new Outer.new Inner();//这种形式很少用。

    但是这种应用不多见,因为内部类之所以定义在内部就是为了封装。想要获取内部类对象通常都通过外部类的方法来获取。这样可以对内部类对象进行控制。

2:私有修饰符。

    通常内部类被封装,都会被私有化,因为封装性不让其他程序直接访问。

3:静态修饰符。

    如果内部类被静态修饰,相当于外部类,会出现访问局限性,只能访问外部类中的静态成员。

    注意;如果内部类中定义了静态成员,那么该内部类必须是静态的。

 

内部类编译后的文件名为:"外部类名$内部类名.java";

 

为什么内部类可以直接访问外部类中的成员呢?

那是因为内部中都持有一个外部类的引用。这个是引用是 外部类名.this

内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。

当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。

 

匿名内部类(对象):没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。

 

匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。

 

匿名内部类的使用场景:

当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。

其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。

--------------------------------------------------------

//面试

        //1

        new Object(){

            void show(){

                System.out.println("show run");                

            }

        }.show();                                    //写法和编译都没问题

        //2

        Object obj = new Object(){

            void show(){

                System.out.println("show run");

            }

        };

        obj.show();                                //写法正确,编译会报错

        

        1和2的写法正确吗?有区别吗?说出原因。

        写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。

        区别:

        第一个可是编译通过,并运行。

        第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时会检查Object类中是否有show方法,此时编译失败。

 

 

异 常:★★★★

--java.lang.Throwable:

Throwable:可抛出的。

    |--Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。

    |--Exception:异常,可以有针对性的处理方式

 

这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。

可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。

 

throw与throws区别:

throws是用来声明一个方法可能抛出的所有异常信息,而throw则是指抛出的一个具体的异常类型。此外throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。

throw用于抛出异常对象,后面跟的是异常对象;throw用在函数

throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数

 

throws格式:方法名(参数)throws 异常类1,异常类2,.....

throw:就是自己进行异常处理,处理的时候有两种方式,要么自己捕获异常(也就是try catch进行捕捉),要么声明抛出一个异常(就是throws 异常~~)。

 

处理方式有两种:1、捕捉;2、抛出。

对于捕捉:java有针对性的语句块进行处理。

try {

    需要被检测的代码;

}

catch(异常类 变量名){

    异常处理代码;

}

fianlly{

    一定会执行的代码;

}

 

定义异常处理时,什么时候定义try,什么时候定义throws呢?

功能内部如果出现异常,如果内部可以处理,就用try;

如果功能内部处理不了,就必须声明出来,让调用者处理。使用throws抛出,交给调用者处理。谁调用了这个功能谁就是调用者;

 

自定义异常的步骤:

1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性(既可以使用throw和throws去调用此类)。

2:通过throw 或者throws进行操作。

 

异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。

 

try catch finally的几种结合方式:

1,

try

catch

finally

 

这种情况,如果出现异常,并不处理,但是资源一定关闭,所以try finally集合只为关闭资源

记住:finally很有用,主要用户关闭资源。无论是否发生异常,资源都必须进行关闭。

System.exit(0); //退出jvm,只有这种情况finally不执行。

 

注意:

如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws。

如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不需要throws声明的。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值