一、面向对象概述 面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。面向对象是基于面向过程。
|--面向过程:强调的是功能行为。如,打开门。
|--面向对象:强调的是功能对象。如,门.打开,先有门才有打开动作
|--面向对象的特点:
是一种符合人们思考习惯的思想。可以将复杂的事情简单化。将程序员从执行者转换成了指挥者完成需求时,这样简化开发并提高复用:
a)先要去找具有所需的功能的对象来用。
b) 如果该对象不存在,那么创建一个具有所需功能的对象。
|--面向对象开发、设计、特征
|--开发:其实就是不断的创建对象,使用对象,指挥对象来做事。
|--设计:其实是管理和维护对象之间的关系。我们一定是写类,因为对象太多,无法写,只能写一个类来代表所有对象
|--特性 :封闭、继承、多态
二、类和对象 |--类 :对现实生活中事物的描述。类中包含属性和行为。
|--属性:一个对象它具有什么特征,我们称它具有什么属性
|--行为:一个对象它有自己的行为,它具有什么行为,我们称它具有什么方法
|--对象:就是这类事物,实实在在存在的个体。可以根据类具有的属性和方法,赋予类不同的数值,来创建不同的对象实例。
三、类 类是Java的核心。在Java中,完成对功能操作封装的单位称为类。类是有共同特性(属性)和操作(行为)定义的实体,类是用于组合各个对象所共有操作和属性的一种机制。
|--创建类的一般格式:
[修饰符] class 类名 [extends父类名] [implements接口名列表]
{
成员变量声明
成员方法声明
}
其中:class、extends和implements都是Java的关键字(保留字)。
类的修饰符主要有public、abstract 、final及缺省访问修饰符等四种。
注意:一个类可以同时有多个修饰符,但是不能有相同的修饰符。当一个类有多个修饰符时,这些修饰符无先后顺序,可任意排列。
|--成员变量/局部变量
|--成员变量:
a)成员变量定义在类中,在整个类中都可以被访问。
b) 成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
c) 成员变量有默认初始化值。
|--局部变量:
a) 局部变量只定义在局部范围内,如:函数内,语句内等。
b) 局部变量存在于栈内存中。
c) 作用的范围结束,变量空间会自动释放。
d) 局部变量没有默认初始化值。
|--成员方法
定义在类内,格式如下:
修饰符 返回值类型 函数名(参数类型 型参1,…………)
{
执行语句;
return 返回值; //如果返回值类型是void,return语句可以不写
}
|--构造方法
构造方法用来实例化对象,具有和类名相同的名称。而且不返回任何数据类型,在构造方法的实现中,也可以进行方法重写。
|--声明格式
修饰符 类名(参数)
{
执行代码
}
|--关注细节:
(1)当一个类中没有定义构造函数时,那么系统就会默认给该类加入一个空参数的构造函数。
(2)当在类中自定义了构造函数后,默认的构造函数就没有了。
(3)这个默认的构造函数的权限和所属类一致。如果类被public修饰,那么默认的构造函数也带public修饰符。如果类没有被public修饰,那么默认的构造函数,也没有public修饰。
(4)当修饰符为private 时,只能本类内创建对象,其它类不可创建此对象。
|--权限修饰符
权限修饰符有public protected default private ,其中修饰后的访问权限如下所示:
java基础—4.面向对象一、面向对象概述二、类和对象三、类四、this关键字五、super关键字六、对象的创建七、封装性八、继承性九、多态性十、Object类(上帝类)十一、static类及static方法十二、内部类十三、接口十四、final关键字十五、abstract类
四、this关键字 this代表它所在函数所属对象的引用。
|--this的应用:
1.当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
2.但凡本类功能内部使用到了本类对象,都用this表示。
|--this用于构造函数:
1.用于构造函数之间进行互相调用。如:this(age);
2.this语句只能定义在构造函数的第一行。因为初始化先执行。
|--this的两种用法:
1、用于区分同名变量的情况,说的成员和局部同名的时候;
2、用于构造函数间调用。
注:
一般函数不能直接调用构造函数,因为this语句不能用在一般函数中,只能用在构造函数间。
五、super关键字 super关键字用于子类建立对象的初始化过程中。在创建派生类的对象时,使用派生类的构造方法对其初始化,不但要对自身的成员变量赋初始值,还要对父类的成员变量赋初始值。
Java语言中,子类调用父类构造方法的原则:
1.在子类的构造方法中,系统会自动添加一条语句:super();它将调用父类的无参构造方法;若父类中没有无参构造方法时,会出错。
2.如父类是有参数的构造方法,子类可以通过在自己的构造方法中使用super(参数);来调用它,且该语句必须是子类构造方法的第一个可执行语句。
六、对象的创建
|--对象的初始化过程
1,把类名.class文件加载到内存中。
2,执行该类中的static代码块,如果有得话,给该类进行初始化。
3,在堆内存中开辟空间,分配内存地址。给对象
4,在堆内存中建立对象的特有属性。并进行默认初始化。
5,对属性进行显示初始化。
6,对对象进行构造代码块初始化。
7,对对象进行对应构造函数初始化。
8,将内存地址赋给栈内存中的对象名变量。
|--单例设计模式(饿汉式、懒汉式)
设计模式是解决某一类问题最行之有效的方法。java有23种设计模式。单例设计模式是解决一个类在内存只存在一个对象的情况。想要保证对象唯一,思考如下:
1.为也避免其它程序过多建立该对象,先禁止其它程序建立该类对象;
2.还为了让其它程序可以访问到该类对象,只好在本类中,自定义一个对象;
3.为了方便其它程序对自定义对象的访问,可以对外提供一些访问方式。
单例设计模式有两个方式:饿汉式、懒汉式
|--饿汉式 特点是 总是先创建对象,类一进入内存就已经创建好了对象
class Single {
private static Single s = new Single();
private Single(){ }
public static Single getInstance(){
return s;
}
}
|--懒汉式 特点是方法被调用时,才初始化,也叫做对象的延时加载。即Single类进内存,对象还没有存在,方法调用时才存在
class Single{
private static Single s = null;
private Single(){}
public static Single getInstance(){
if(s==null)
{
synchronized(Single.class)
{
if(s= null )
s = new Single();
return s;
}
}
}
}
七、封装性 封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式,封装的好处是
|--好处
1.将变化隔离
2.便于使用
3.提高重用性
4.提高安全性
|--封装的原则
1.将不需要对外提供的内容都隐藏起来;
2.把属性都隐藏,提供公共方法对其访问;
|--封装的方法
private关键字:权限修饰符;用于修饰类中的成员(成员变量,成员函数);私有只在本类中有效。
常用之一:
将成员变量私有化,对外提供对应的set,get方法对其进行访问。提高对数据访问的安全性。私有是封装的表现形式之一。
八、继承性 当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可。继承是让类与类之间产生关系,有了这个关系,才有了多态的特性。继承提高了代码的利用性。
|--8.1 继承的使用规则:
1.Java语言中,只支持单继承,不支持多继承
2.必须是类与类之间有所属关系才可以继承。这种所属关系的表示为is a
3.类可以多重继承
|--8.2 继承的使用——使用一个继承体系中的功能
想要使用体系,先查体系中父类的描述,因为父类中定义的是该体系中的共性功能。通过了解共性功能,就可以知道该体系的基本功能。这样这个体系就可以基本使用了。在具体调用时,要创建最子类的对象。原因:
1.因为有可能父类不能创建对象。
2.创建子类对象可以使用更多的功能,包括基本的也包括特有的。
简单一句就是:查阅父类功能,创建子类对象使用功能
|--8.3 子父类中,成员的特点
|--(1)变量
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this。子类要访问父类中的同名变量,用super。
super的使用和this的使用几乎一致,且两者都存在于方法区中。
|--this表示本类对象的引用。
|--super表示父类对象的引用。
|--(2)函数
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中。但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。子类同时具有父类方法中的内容时,可以用super.方法();
|--重写的规则
(1)子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
(2)静态只能覆盖静态。
(3)父类中的私有方法不能被重写。
|--重载与重写
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。
|--(3)构造函数
在对子类对象进行初始化时,父类的构造函数也会运行。那是因为子类的每一个构造函数默认第一行有一条隐式的语句super()。super()会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super(),也只能在第一行。
子类一定要访问父类中的构造函数的原因是父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
子类的所有构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super();当父类中没有空参数的构造函数时,子类必须手动通过supe语句或者this语句形式来指定要访问的构造函数。当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
小知识点:
为什么this()和super()不能在同一个构造函数中?
因为它两不能在同一行。
为什么不能再同一行?
因为初始化动作要先做。在子类构造函数中必有一个this语句或者super语句。
九、多态性 多态主要表现在:向上转型、向下转型
多态可以理解为事物存在的多种体现形态。
|--多态的体现
1.父类的引用指向了自己子类的对象。
2.父类的引用也可以接收自己的子类对象。
|--多态的前提
1.类与类之间必须有关系,要么继承,要么实现。
2.存在覆盖。父类中有方法被子类重写。
|--多态的利与弊
利:提高了程序的可扩展性和后期可以维护性。
弊:只能使用父类中的引用访问父类中的成员。也就是说使用了多态,父类型的引用在使用功能时,不能直接调用子类中的特有方法。
|--多态中的成员特点
|--函数
编译看左边,运行看右边……
Father fu = new Sun();
注意:如果是静态函数的话,无论编译和运行都是看左边,因为静态的方法不属于对象,只属于类。static方法先加载……
|--变量
无论编译和运行,都看左边
|--多态的应用
1.定义好工具类,即将共同行为封装在一个类中。
2.对类型进行抽取,---->多态的产生。
3.操作同一父类型,对其中的子类型均可操作
十、Object类(上帝类) Object:是所有对象的直接后者间接父类,传说中的上帝类,该类中定义的肯定是所有对象都具备的功能。
如果自定义类中有与父类相同的功能,没有必要专门定义另一个名称的函数,可以沿习父类的名称,即重写函数,实现功能。
Object类最最重要的功能是体现在多态性上,父类的引用指向子类对象。这样可以简化代码的书写。增加功能的扩展性。
|--equals(Object obj )
|--toString()
十一、static类及static方法 static是一个修饰符,用于修饰成员变量和成员函数。当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员。
|--静态利弊:
|--利处:对对象共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。
|--弊端:生命周期过长。访问出现局限性。(静态虽好,只能访问静态)。
|--static特点:
(1)随着类的加载而加载。即:静态会随着类的消失而消失,说明它的生命周期最长。
(2)优先于对象存在。静态是先存在。对象是后存在。
(3)被所有对象所共享。
(4)可以直接被类名所调用。由于静态成员可以直接被类名调用,因此静态成员变量又称为类变量。而非静态成员变量又被称 为实例变量。
|--实例变量和类变量的区别:
(1)存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
(2)生命周期。
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
|--静态的分类
|--静态函数
当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。
|--静态变量
1.当对象中出现共享数据时,该数据被静态所修饰。
2.对象中的特有数据要定义成非静态存在于堆内存中。
|--静态代码块
随着类的加载而执行,执行一次。并优先于主函数。用于给类进行初始化。
格式:
static
{
静态代码块中的语句。
}
十二、内部类 分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。这时就用到内部类来描述。
|--12.1 内部类的访问规则
|--内部类访问外部类
可以直接访问外部类中的成员,包括私有;
|--外部类要访问内部类
必须建立内部类对象;
|--非静态情况:new Outer().new Inner().function()
|--访问static内部类的非静态成员:new Outer.Inner().function()
|--访问static内部类的static方法 Outer.Inner.function();
注意:
(1)当外部类中的静态方法 访问内部类时,内部类也必须是static 的。
(2)当内部烦躁定义了静态成员,该内部类必须是static的
public class FunTest {
public static void main(String[] args) {
// 非静态外部类,非静态内部类的访问成员方式
new Outer().new Inner().function();
// 非静态外部类,静态内部类,非静态方法的访问方式
new Outer.StaticInner().function();
// 非静态外部类,静态内部类,静态方法 的访问方式
Outer.StaticInner.staticFunction();
}
}
class Outer {
int x = 0;
// 静态内部类
static class StaticInner {
// 静态方法
public static void staticFunction() {
System.out.println("这个是静态内部类的静态成员");
}
// 非静态方法
public void function() {
System.out.println("这个是静态内部类的非静态成员");
}
}
// 非静态方法
class Inner {
// 这里面只能定义非静态的方法
public void function() {
System.out.println("这个是非静态内部类的非静态成员");
}
}
}
|--12.2 内部类分类
|--(1)成员内部类
定义在一般成员位置上的内部类,叫成员内部类,下面内部类的修饰符为public时,在其它类创建对象方法: 外部类名.内部类名 变量名 = new 外部类().new 内部类(),即:Outer.Inner in = new Outer().new Inner()
<span style="font-size:14px;">public class Outer{
private int x;
public class Inner{
private int x ;
public void doit(int x ){
x++;
this.x++;
Outer.this.x++;
}
}
}</span>
|--(2)局部内部类
在局部位置定义的类,如在类的方法或任意的作用域中均可以定义内部类
publci OuterClass{
public void doit(){
System.out.print("test");
clas InnerClass(){
private int x;
InnerClass(int x){
this.x = x;
}
}
}
}
|--(3)匿名内部类
匿名内部类其实就是一个子类对象。前提是:存在一个类或者接口,这里的类可以是具体类也可以是抽象类。
使用的格式如下:
new 类名或接口( ){重写的方法}
如:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("haha");
}
});
|--(4)静态内部类
在内部类前添加修饰符static ,这个内部类就变为静态内部类。有以下2点规则:
1.静态内部类可以声明静态变量,但非静态不可以;
2.静态内部类不可以使用外部类的非静态成员
public class Outer{
int x =0;
static class Inner{
//x=1; 这句是错的,不可以引用外部的非静态成员
void doit(){
System.out.pritln("静态内部类测试");
}
}
}
|--(5)内部类的继承 与普通类一样,也可以被继承,格式如下:
public class ClassA{
class ClassB{
}
}
pulbic TestClass extends ClassA.ClassB{
TestClass(ClassA a){
a.super();
}
}
十三、接口 接口,可以被认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。
|--13.1 定义格式及使用格式:
|--(1)定义格式
interface 接口名
{
void function();
}
|--(2)使用格式
子类名 implements 接口名1,接口2…………
{
void function()
{实现方法}
}
|--(3)格式要求
(a)接口中常见定义:常量,抽象方法。
(b)接口中的成员都有固定修饰符,编码时可不写,编译器会自动加上。
常量:public static final
方法:public abstract
(c)接口中的成员都是public的。
|--13.2 接口的特点
(1)接口是对外暴露的规则。
(2)接口是程序的功能扩展。
(3)接口的出现降低耦合性。
(4)接口可以用来多实现。这也是对多继承不支持的转换形式。java支持多实现。
(5)类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
(6)接口与接口之间可以有继承关系。而且可以多继承。
注:
1,接口不可以创建对象的,因为有抽象方法。需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。
2,实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写。
|--13.3 抽象类与接口对比
|--共性:都是不断向上抽取出来的抽象的概念。
|--区别:
(1)抽象类体现继承关系,一个类只能单继承。
接口体现实现关系,一个类可以多实现。同时接口与接口之间有继承关系。
(2)抽象类是继承,是 "is a "关系。
接口是实现,是 "like a"关系。
(3)抽象类中可以定义非抽象方法,供子类直接使用。
接口的方法都是抽象,接口中的成员都有固定修饰符。
(4)抽象类中可以私有变量或方法。
接口中的常量和方法都是public修饰的权限。
十四、final关键字 作为修饰符,可以修饰类、函数、变量:
1.被修饰的变量,是常量只能赋值一次
2.被修饰的函数不能重写
3.被修饰的类不能被继承
十五、abstract类 在Java中抽象类的
|--语法格式为:
abstract 抽象类 Demo
{
abstract void method1();
abstract void method2();
…
}
|--规则及用法
1.抽象方法必须定义在抽象类中;
2.必须用abstract关键字标识;
3.抽象类不可创建对象
4.抽象类中的方法要被使用,必须由子类复写所有的抽象方法,再建立子类对象调用
5.如果子类只覆盖了部分抽象的方法,那么该子类还是一个抽象类
|--特殊
抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象;