继承:
1,提高了代码的复用性。
2,让类与类之间产生了关系,有了这个关系,才有了多态的特性。
在Java语言中只支持单继承,不支持多继承。
因为多继承容易带来安全隐患:当多个父类中定义了相同的功能,当功能内容不同时,子类对象不确定要运行哪一个。
但是java保留这种机制,并用另一种体现形式来完成表示,多实现。
Java支持多层继承。也就是一个继承体系。
类中成员:
1,函数
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。
覆盖:
注意:1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
final关键字
final:最终,作为修饰符。
1,可以修饰类,函数,变量。
2,被final修饰的类不可以被继承。为了避免被继承,被子类覆写功能。
3,被final修饰的方法不可以被覆写。
4,被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
5,内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
多态:可以理解为事物存在的多种体现形态。
(注意:多态自始自终都是子类的对象在做变化)
1.多态的体现:
父类的引用指向了自己的子类对象。即父类的引用也可以接受自己的子类对象。
2.多态的前提:
必须是类与类之间有关系,要么继承,要么实现。
通常,需要存在覆盖(重写)。
3.多态的利弊:
多态的出现大大提高了程序的扩展性。但是只能使用父类的引用访问父类中的成员。
4.多态的应用:
abstract class Student {
public abstract void study();
public void sleep(){
System.out.println("躺着睡");
}
}
class BaseStudent extends Student{
public void study(){
System.out.println("bs study");
}
}
class AdStudent extends Student{
public void study(){
System.out.println("ad study");
}
public void sleep(){
System.out.println("做着睡");
}
}
class DoStudent{
public void doSomeing(Student stu){
stu.study();
stu.sleep();
}
}
class DuotaiDemo{
public static void main(String[] args){
DoStudent ds=new DoStudent();
ds.doSomeing(new BaseStudent());
ds.doSomeing(new AdStudent());
}
}
5.多态使用的注意事项:
1.(非静态成员函数特点):
在编译时期:参阅引用型变量所属的类中是否有调用方法,如果有,编译通过,没有则失败
在运行时期:参阅对象所属的类中是否有调用方法。
编译看所属类,运行看对象。
(静态成员函数特点):
根据内存的存储情况,参考的应该是所属类。
2.在多态中,成员变量特点:无论编译或运行,都考虑所属类而不是对象。
--------------------------------------------------------------------------------------------
多态的应用举例:电脑主板通过PCI接口与各设备连接,用编程的方式体现面向对象中多态的特性
interface PCI
{
public void open();
public void close();
}
class NetCard implements PCI
{
public void open(){
System.out.println("netcardruns");
}
public void close(){
System.out.println("netcardclose");
}
}
class SoundCard implements PCI
{
public void open(){
System.out.println("soundcardruns");
}
public void close(){
System.out.println("soundcard close");
}
}
class MainBoard
{
public void run(){
System.out.println("mainboard runs");
}
public void usePCI(PCI p){ //多态的应用:PCI p =new NetCard();
//因为接口不能创建对象,因此接口型引用指向自己的子类对象,即指向自己的实现。
if (p!=null){
p.open();
p.close();
}
}
}
class Computer
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
/ *
内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有。
内部类可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
2.外部类需要访问内部类,必须建立内部类对象。
访问格式:
static: 内部类就具备了static的特性。
当内部类被静态修饰后,只能访问外部类中的静态成员,出现了访问的局限性。
.在外部类中直接访问static内部类的非静态成员:(创建内部类对象)
newOuter.Inner().function();
在外部类中直接访问static内部类的静态成员:(直接类名调用)
Outer.Inner.function();
注意:当内部类中定义了static成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
******内部类定义在局部时:
******1.不可以被成员修饰符修饰;
******2.可以直接访问外部类中的成员,因为还持有外部类中的引用;但是不可以访问他所在的的局部中的变量,只能访问被final修饰的局部变量。
class Outer
{
private static int x=3;
/*内部类可以被私有修饰,外部类则不行
private class Inner
{
int x=4;
void function(){
int x=6;
System.out.println("inner:" + x);
System.out.println("inner:"+ this.x);
System.out.println("inner:" + Outer.this.x);
}
}
static class Inner
{
static void function(){
System.out.println("inner:"+x);
}
}
static class Inner2
{
void show(){
System.out.println("Inner2 show");
}
}
public static void method(){
/ *
Inner in = new Inner();
in.function();
* /
new Inner2().show();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
//Outer out = new Outer();
//out.method();
/ *
直接访问内部类中的成员。
错误方法:
Inner in = new Inner();
in.function();
正确方法:
Outer.Inner in = new Outer().newInner();
in. function();
* /
new Outer().method();
}
}
-------------------------------------------------------------------------------------------------
/ *
匿名内部类:
1.匿名内部类其实就是内部类的简写格式。
2.定义匿名内部类的前提:
内部类必须是继承一个类或者实现一个接口。
3.匿名内部类的格式: new 父类或者接口{定义子类的内容}
4.匿名内部类就是一个匿名子类对象,并且带有内容。
5.匿名内部类中定义的方法最好不超过3个。
一般当传递参数是一个对象,返回值是一个对象等等情况,可以考虑到匿名内部类的使用,以简化代码
当没有接口或者抽象类的时候,仍需使用匿名内部类,可以创建Object对象,形如new Object
*************************************
public void function(){
new AbsDemo(){
void show(){
System.out.println("x="+x);
}
}.show();
}
在function中也可以利用父类引用指向子类对象,为对象起名:
public void function(){
AbsDemo abs =new AbsDemo(){
void show(){
System.out.println("x="+x);
}
void show2(){
System.out.println("absdemo");
}
};
abs.show();
abs.show2();//编译失败,因为接口里没有show2的定义
结论是:当使用直接子类对象时,可以调用特有函数;当建立一个父类引用时,不能调用特有函数。