黑马程序员——java基础_面向对象

时间:2022-02-28 12:07:17
------- android培训 java培训 、期待与您交流! ----------

 

理解面向对象:

是一种符合人们思考习惯的思想
可以将复杂的事情简单化
将程序员从执行者转换成了指挥者
完成需求时:
?先要去找具有所需的功能的对象来用。
?如果该对象不存在,那么创建一个具有所需功能的对象。
?这样简化开发并提高复用。

?将功能封装进对象,强调具备了功能的对象。 
面向对象是基于面向过程的。

设计的过程:其实就是在管理和维护对象之间的关系。

开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。

 


面向对象的特征: 

三大特征:封装、继承、多态。

封装(encapsulation) : 
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
将变化隔离。
便于使用。
提高重用性。
提高安全性。
封装原则:
将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。

继承(inheritance):

继承的关键字:extends

继承的由来:
如果多个类中存在相同的属性和方法,那么可以把相同的部分抽取出来,放到一个单独的类中,然后让原来这些类去继承这个单独的类。这样原来的类就无需再去定义这些相同的
属性和方法了。

继承代码体现:

class SuperClass {
public int a;
public void fun1() {}
}

class Class1 extends SuperClass {
}

class Class2 extends SuperClass {
   int b;
   public void fun3() {}
}

Java只支持单继承,不支持多继承。
?一个类只能有一个父类,不可以有多个父类。
?class SubDemo extends Demo{}         //ok
?class SubDemo extends Demo1,Demo2...      //error


Java支持多层继承(继承体系)
?class A{}
?class B extends A{}
?class C extends B{}


定义继承需要注意:
?不要仅为了获取其他类中某个功能而去继承
?类与类之间要有所属( " is a " )关系,xx1是xx2的一种。

继承的好处:
1,
提高了代码的复用性。
2,让类与类之间产生关系,为多态提供了先决条件。

Java中的继承。
1
java只支持单继承,不支持多继承。为啥呢?

    答案:因为继承了多个父类如果有相同方法时,子类对象不确定运行哪一个。


 2,Java还支持多层继承。

A-->B--->C  原来可以形成继承体系。
想要使用体系功能,"查阅父类功能,建立子类对象调用功能。"
注解:父类的由来其实是由事物中的共性内容不断向上抽取而来的。
所以父类中定义的是该体系中的最基本,最共性功能。

多态(polymorphism) : 
程序中体现:

父类或者接口的引用指向或者接收自己的子类对象。
好处和作用:

多态的存在提高了程序的扩展性和后期可维护性

前提:
?需要存在继承或者实现关系
?要有覆盖操作


多态性:

1 是一个(is a),向上转型
可以把子类的实体赋给父类的引用。
Person p = new Student();//用p指定Student的实体对象

Object obj = new Student();
子类的实体更加强大,而父类的引用是越来越通用!

2 调用的是子类的方法还是父类的方法
子类的方法,即由实体的类型来决定调用的是哪个类的方法。
可以调用哪些方法,由引用的类型来决定。

3 向上转型后能调用的方法个数被引用类型限制
可以调用哪些方法,由引用的类型来决定。

父类的引用可以指向子类的实体
子类的引用就不能指定父类的实体。

4 向下转型不安全
向上转型:用父类的引用指向子类引用指定的实体。这是安全的!
向下转型:用子类的引用指向父类引用指向的实体。这是不安全的!

向下转型的目标,使用子类的引用,来调用更多的方法。
没有向上转型,是否可以向下转型?不可能!

父 s = 子,可以,向上转型
子 c = 父,不可以,需要强制转换!

5 判断“是一个”的关系(instanceof运算符)

左边是引用,右边是类型。
p instanceof Person:表达式结果是boolean值,判断p指向的实体能不能用Person类型的引用指向。
s instanceof Person:判断s指向的实体能不能用Person类型的引用指向。
p instanceof Student:判断p指向的实体能不能用Student类型的引用指向。

6 多态调用的概念
重载:编译器确定要调用的是哪一个方法。同一条调用语句,但调用的哪个重载版本的方法是多态的!
重写:JVM确定调用的是哪一个方法。同一个类型的引用,调用的是哪个类的方法是多态的!

7 运行时多态的前提
 继承或实现, 重写方法:子类需要重写(覆盖)父类的方法。
向上转型:使用父类(或者接口)的引用指向子类(或者实现类)的对象实体。然后调用重写方法。

 

 

类的定义:
生活中描述事物无非就是描述事物的属性和行为。
?如:人有身高,体重等属性,有说话,打球等行为。
Java中用类class来描述事物也是如此
?属性:对应类中的成员变量。
?行为:对应类中的成员函数。
定义类其实在定义类中的成员(成员变量和成员函数)。

 

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


成员变量:

?成员变量定义在类中,在整个类中都可以被访问。
?成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
?成员变量有默认初始化值。


局部变量:
?局部变量只定义在局部范围内,如:函数内,语句内等。
?局部变量存在于栈内存中。
?作用的范围结束,变量空间会自动释放。
?局部变量没有默认初始化值。

 

内部类的访问规则:
1,
内部类可以直接访问外部类中的成员,包括私有。
       之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2,外部类要访问内部类,必须建立内部类对象。

访问格式:
1, 
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
 可以直接建立内部类对象。
 格式
外部类名.内部类名  变量名 = 外部类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();

2,  当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装。
static:内部类就具备static的特性。
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().function();

注意:当内部类中定义了静态成员,该内部类必须是static的。
  当外部类中的静态方法访问内部类时,内部类也必须是static的。

什么时候使用内部类呢?
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容。

匿名内部类:
1,匿名内部类其实就是内部类的简写格式。
2,定义匿名内部类的前提:
           内部类必须是继承一个类或者实现接口。
3,匿名内部类的格式:  new 父类或者接口(){定义子类的内容}
4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。 可以理解为带内容的对象。
5,匿名内部类中定义的方法最好不要超过3个。

类与对象的关系:

  使用计算机语言就是不断的在描述现实生活中的事物。

java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。
对象即是该类事物实实在在存在的个体。

类与对象的关系如图:

黑马程序员——java基础_面向对象

  
可以理解为:
?类就是图纸
?汽车就是堆内存中的对象
 

创建对象,使用对象:

class Car//对Car这类事物进行描述

{

  String color = "red";

  int num = 4;

  void show()

  {

  System.out.println("color="+color+"..num="+num);

  }

}

class CarDemo

{

  public static void main(String[] args)

  {

  Car c = new Car();//建立对象

  c.color = "black";//对对象的属性进行修改

  c.show();//使用对象的功能。

  }


对象内存结构:

黑马程序员——java基础_面向对象

匿名对象: 

匿名对象是对象的简化形式
匿名对象两种使用情况
当对对象方法仅进行一次调用的时
匿名对象可以作为实际参数进行传递

 

private关键字:


是一个权限修饰符。
用于修饰成员(成员变量和成员函数)
被私有化的成员只在本类中有效。
常用之一:
将成员变量私有化,对外提供对应的set ,get方法对其进行访问。提高对数据访问的安全性。
函数:
 子类可以直接访问父类中非私有的成员函数。
特殊情况:当子类中定义了与父类一模一样的方法时,会发生覆盖操作。大多指的是非静态方法。
 最终会运行子类的方法,父类相当于被覆盖了。
  函数的另一个特性:覆盖(重写,复写)。

什么叫重写(覆盖)父类方法
父类的方法,子类也有。
父类的方法,子类中除了方法体内容不一样,其他都一样。
子类重写父类方法要求:
方法名与父类方法名相同;
方法参数列表与父类方法相同;
返回值类型与父类方法相同(JDK1.5,子类可以返回父类返回值类型的子类型);

如果重写了父类方法,那么外界调用的就是子类的方法
当调用子类对象的方法,如果子类自己有就调用自己的,如果没有才会去父类的。
其实是由对象实体的类型决定调用的哪个方法。

什么时候用覆盖啊?
  当父类的功能要被修改时,不建议修改源码。因为是灾难。
  只要通过一个类继承原有类,定义一个新的升级后的功能即可。
  但是功能是相同的,只是实现方法改变。这是子类可以沿袭父类中的功能定义,
  并重写功能内容。这就是覆盖。

覆盖很爽,但是有注意事项:

重写的要求:
1 
访问修饰只能等于父类方法修饰,或者更加宽松
方法名:必须相同
参数列表:必须相同
返回类型:1.5之前,必须相同,1.5之后又添加了:子类可以返回父类方法的返回类型的子类型
修饰符:只能比较父类更加宽松!例如父类用的是protected或者是默认(不写访问修饰符),那么只类,或者与父类相同,或者更加宽松!
2 子类声明的异常只能越来越少,而不能越来越多。

3 private、final和static方法不能重写
  

final关键字:

1 final修饰的类不能有子类
  final修饰的类不能被继承!

2 final修饰的方法不能被重写
  final修饰的方法不能被重写!

3 final方法不能重写,也就没有多态一说
  final方法不能被重写,没有了重写就没有了多态的前提!


构造函数:
 构造函数可以本类进行对象初始化,也可以给子类对象进行初始化。
子类对象初始化过程:
子类中的所有构造方法都会访问父类中空参数的构造函数,
因为每一个构造函数的第一行,都有一句隐式的super语句。
为什么要有这条语句?
因为子类会获取到父类中的数据,必须要先明确父类对数据的初始化过程。

当父类中没有空参数构造函数时,子类构造函数必须通过super句来明确要访问的父类中指定的构造函数。

当时子类构造函数也可以通过this语句访问本类中的构造函数。
但是子类中肯定,至少有一个构造函数会访问父类。

特点:
函数名与类名相同
不用定义返回值类型
没有具体的返回值。
作用:
给对象进行初始化。
注意:
默认构造函数的特点:
多个构造函数是以重载的形式存在的


 
抽象类:

其实就是在分析事物时,事物中的功能有些是不明确的内容的。这些不明确内容就是抽象的。
可以通过抽象函数来描述。

抽象函数一定要定义在抽象类中,因为,抽象函数所在类,也必须被抽象标识。

写法特点:
1,抽象函数只对函数进行声明,没有函数主体。
2,抽象类和抽象函数都需要用abstract修饰。
3,抽象类不可以进行实例化。
4,想要使用抽象功能,必须通过子类覆盖了父类中所有的抽象方法后,才可以对子类实例化。
如果只覆盖了部分抽象方法,那么子类还是一个抽象类。

也可以理解为:抽象类是一个父类,是不断向上抽取而来的,
在抽取过程中,只抽取了方法声明,但没有抽取方法实现。

抽象类和一般类差不多。
区别:

抽象类可以定义抽象方法。
抽象类不可以建立对象。

其实抽象类一样用于描述事物,既可以定义抽象方法,也可以定义非抽象方法。

接口
初期理解:接口看上去是一个特殊的抽象类。里面存的都是抽象方法。


  格式:
1,
通过interface来定义。
2,接口中常见成员:常量,抽象方法。
而且这些成员都有固定的修饰符。
常量:public static final
方法:public abstract
3,接口中的成员都是共有的。
4,一个类可以对接口进行多实现,也弥补了多继承带来的安全隐患,所以java对多继承进行了改良。
用多实现方法来体现多继承的特性。
5,一个类可以继承一个类的同时,实现多个接口。
6,接口与接口之间是继承关系,而且可以多继承。

 应用特点:
1,接口是对外暴露的规则。
2,接口是功能的扩展。
3,接口的出现降低了耦合性。
举例。如usb。pci,主板。插座。


抽象类和接口异同:
相同:
1,
都可以在内部定义抽象方法。
2,通常都在顶层。
3,都不可以实例化,都需要子类来实现。

不同点:
1,
抽象类中可以定义抽象方法和非抽象方法,
而接口中只能定义抽象方法。
2,接口的出现可以多实现。
抽象类只能单继承。
也就是说:接口的出现避免了单继承的局限性。
3,继承和实现的关系不一致。继承:is a,实现:like a 

 
static关键字:
?用于修饰成员(成员变量和成员函数)
被修饰后的成员具备以下特点:
随着类的加载而加载,所以它的生命周期最长。
优先于对象存在
被所有对象所共享
可以直接被类名调用
使用注意
静态方法只能访问静态成员
静态方法中不可以写this,super关键字
主函数是静态的
永远不死的static属性
使用类的静态属性
使用类的静态方法
创建本类对象时
都会加载这个类!
加载类时给静态属性分配内存空间。
加载完成后,如果存在显示初始化语句,那么执行。
3 static属性的空间在方法区中
4 static属性的默认值:分配内存时已经指定的了默认值。与实例属性的默认值是一样的
5 static属性的显示初始化:默认值之后才会执行显示初始化语句。

静态使用注意事项:
1,
静态方法只能访问静态成员。
非静态方法既可以访问静态也可以访问非静态。
2,静态方法中不可以定义this,super关键字。
因为静态优先于对象存在。所以静态方法中不可以出现this。
3,主函数是静态的。