首页 > 编程语言 >Java基础-面向对象概述

Java基础-面向对象概述

时间:2024-02-27 17:35:42浏览次数:28  
标签:Java 变量 对象 子类 接口 面向对象 概述 父类 方法

本章重点针对面向对象的三大特征:继承、封装、多态进行详细的讲解。另外还包括抽象类、接口、内部类等概念。很多概念对于初学者来说,更多的是先进性语法性质的了解。

1. 面向对象-继承:

1. 继承的实现:

继承通过如下格式实现:

class 子类名 extends 父类名 [implements <接口名>]{

}
  1. 继承让我们更加容易实现类的扩展。比如:我们定义了人类,在定义Boy类就只需要扩展人类即可。实现了代码的重用。子类再保留父类的基本属性与行为的基础之上,可以增加新的属性和行为,或者修改父类的属性与行为。
  2. 从英文字面意思理解,extends的意思是“扩展”。子类是父类的扩展。现实世界中的继承无处不在。父类派生子类,子类继承父类,子类也可以在派生子类。这样就形成了层次结构。

2. 继承使用要点:

  1. 父类也称作为超类、基类、派生类等。
  2. Java中只有单继承,没有C++那样的多继承,多继承会引起混乱,使得继承链过于复杂,可能会导致二义性,系统难以维护。
  3. java中类没有多继承、接口有多继承(实现)。
  4. 子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如:父类私有的属性和方法).
  5. 如果定义一个类时,没有调用extends,则他的父类是:java.lang.Object;
    • Object类是java预定义的所有类的父类,包含了所有java的公共属性,其中定义的属性和方法均可被任何类所使用、继承和修改。
  6. 子类继承父类时遵循普遍性原则和特殊性原则:
    • 普遍性原则:指子类继承父类中已有的成员变量和方法
    • 特殊性原则:指子类可以增加父类中没有的方法和变量,或者修改父类中已有的变量和方法。

3. super关键字的用法:

super是直接父类对象的引用,可以通过super来访问父类中被子类覆盖的方法或属性。

  1. 子类在继承父类时,可能会出现变量隐藏、方法覆盖等现象。

变量隐藏指子类的成员变量与父类的成员变量同名,此时父类的成员变量被隐藏。

方法覆盖指的是子类的方法名与父类的方法名同名,方法的返回值类型、入口参数的数目、类型、顺序均相同,只是方法实现的功能不同,此时弗雷德方法被覆盖。

如果子类需要调用或访问父类被隐藏的变量或被覆盖的方法,可以使用super关键字实现。

【注意】:但是创建子类对象的时候并不会创建一个父类对象,因为加入我创建子类的同时会自动创建父类对象的话,复杂的继承链会让堆内存立刻Overflow。所以说父类对象只是一个标识符,并非指向父类对象,而且this.hashCode方法和super.hashCode方法指向的都是同一块内存。super其实是一种用来访问父类成员的一种标识符而已。当继承中出现了变量隐藏和方法覆盖的时候,super就是一种访问父类属性和调用父类方法的一种手段。

  1. super关键字除了可以调用父类被隐藏的变量和被覆盖的方法之外,还可显式调用父类构造方法。

综上所述:super关键字的三个情况:
1.用来访问父类中被覆盖的方法
2.用来访问父类中被隐藏的成员变量
3.用来调用父类的构造方法

4. 子类对象的构造:

调用构造方法遵循以下几条规则:

  1. 创建对象时调用该类的父类构造方法。调用父类的构造方法很简单,只要在类的构造方法的方法体中,将第一条写为super语句即可。super可以调用父类的任何一个带入口参数或不带入口参数的构造方法。

  2. 如果类的构造方法中第一条没有用super来到用的构造方法,则编译器也会默认用super()调用父类的无参构造方法。

  3. 如果某个类的构造方法的第一条语句是用this来调用本类的另外一个构造方法,那么java系统就不会默认用这个构造方法调用父类的构造方法。(但是一定会调用父类的构造方法)

  4. 如果父类中定义了有参构造方法,则java系统不在提供默认的无参构造方法,因此在子类的构造方法中一定需要显式通过super调用父类有参构造方法。

5. 对象类型转化:

  1. 如同基本数据类型之间的类型转换,对象也可以在一定范围内进行类型转换。

    由于子类拥有父类的方法和属性,因此java中的子类对象可以向上转换为父类对象(也成为上转型对象)。允许将子类的实例赋值给父类的引用,也允许一个父类的引用指向子类对象。

SuperClass superClass = new SubClass();//父类的引用指向了子类对象
  1. 但是反过来,一个父类对象的类型未必可以向下转换成子类对象。因为子类具有的信息,父类未必包含,这种转换是不安全的。

    只有当父类引用实际上指向一个子类对象时,才可以进行这种转换。

SubClass subClass = new SuperClass();//错误!!!
  1. 类型转换的某些问题:

    1. 上转型对象不能操作子类新增加的成员变量和成员方法。
    2. 上转型对象可以代替子类对象调用子类重写的实例方法。
    3. 上转型对象可以调用子类继承的成员变量和隐藏的成员变量。
  2. 对象转换不仅只发生在对象赋值的情况下,也会发生在方法调用的参数传递的情况下。如果一个方法的形式参数定义的是父类对象,那么调用这个方法时,可以使用子类对象作为实际参数。

6. instanceof运算符:

instanceof是二元运算符,左边是对象,右边是类:当对象是右边的类或子类所创建的对象时,返回true;否则,返回false。

7. 方法的重写(Override):

子类通过重写父类的方法,可以用自身的行为去替换父类的行为。

方法的重写需要符合下面三个重点:

  1. “==”:方法名、参数列表相同。
  2. “<=”:返回值类型和声明异常类型,子类小于等于父类。
  3. “>=”:访问权限,子类大于等于父类。

8. toString方法的重写和equals方法的重写:

toString方法

目的是为了打印对象的内容,可根据自己的格式进行重写。

equals方法

  1. "=="和equals方法的区别:
    • "=="代表比较双方是否相同,如果是基本类型,则表示值相等。如果是引用类型则表示地址相等,即是否为同一个对象。
    • equals方法是由Object类中定义,提供定义"对象内容相等"的逻辑,即:内容相等即可。
  2. 重写equals方法
    • equals在Object类中默认为:equals方法和==的作用一样,即看两个对象的HashCode是否相同。我们可以根据自己的需求重写equals方法。
  3. JDK提供的一些类,如String、Date、包装类,重写了Object的equals方法,调用这些类的equals方法,x.equals(y),当x和y所引用的对象是同一类对象且内容属性相等时(不一定是相同对象),返回true,否则返回false。

2. 面向对象-封装:

面向对象程序设计的一个特性就是封装,将实体特征的属性隐藏起来,对象与外界仅通过公共方法进行交流,这样可以提高程序的可靠性、安全性、改善程序的可维护性。数据的隐藏与开放对外的接口可以通过访问权限控制符来实现,权限控制符可以用来设置类、成员变量、成员方法等的访问权限。

1. 封装的实现-使用访问控制符:

Java提供public、protected、default、private四种访问控制符,在类、成员变量、成员方法的前面均可以使用访问控制符关键字,没有显式使用的为default控制类型。

  1. private:表示私有,只有自己类可以访问。
    • private只能修饰成员变量和成员方法
  2. default:表示没有修饰符修饰,只有同一个包的类能访问。
    • 默认权限,当类、接口、成员变量和成员方法没有设置访问控制符时,默认为dufault。
  3. protected:表示可以被同一个包的类以及其他包中的子类访问。
    • 可以用来修饰成员变量和成员方法,不可以修饰类和接口。
  4. public:表示可以被该项目中的所有包中的所有类访问。
    • 可以用来修饰类、接口、成员变量和成员方法。为了保证数据的隐藏性和安全性,不建议把所有的成员变量或方法全部设置为public,通常只将公共类或公共接口的成员方法指定为public

2. 封装的使用细节:

类的属性的处理:

  1. 一般使用private访问权限
  2. 提供相应的get/set方法来访问相关属性,这些方法通常都是public修饰的,以提供对属性的赋值与读取操作(注意:boolean类型的变量的get方法时is开头!)。
  3. 一些只用于本类的辅助性方法可以用private修饰,希望其它类调用的使用public修饰。

getInofo和setInfo

处于对系统设计的安全性考虑,一般将类的成员属性定义为private形式保护起来,而将类的成员方法定义为public形式对外公开,这是类封装特性的一个体现。一般来说,类中应提供相应的get方法(得到private成员变量的值)和set方法(修改private成员变量的值),以便其它类操作该类的private成员变量。

3. 面向对象-多态:

多态指的是:同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。即:不同类的对象收到相同的信息时,得到不同的结果。

1. 静态多态性和动态多态性:

静态多态性:

指定义在一个类或一个函数中的同名函数,他们根据参数列表(类型以及个数)区别语义和执行的功能。

动态多态性/运行时多态:

指定义在一个类层次的不同类中的重载函数,他们具有相同的函数原型,需要根据指针指向的对象所在类来区别语义,它通过动态联编实现。

2. 多态的使用要点:

  1. 多态指的是方法的多态,不是属性的多态(多态与属性无关)。
  2. 多态的存在要有三个必要条件(主要是运行时多态):
    1. 继承
    2. 方法重写
    3. 父类引用指向子类对象
  3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。

4. 非访问控制符:

1. static:

1. 修饰类变量:

如果一个数据需要被所有对象共享使用的时候,那么即可使用static修饰该成员变量。

访问方式:

  1. 可以使用对象进行访问。 格式:对象.静态属性名

  2. 可以使用类名进行访问。 格式:类名.静态属性名
    推荐使用类名进行访问。

  3. 静态的成员变量可以使用类名或者是对象进行访问,不需要创建对象就可以访问类变量。

  4. 非静态的成员变量只能使用对象进行访问,不能使用类名直接访问。

  5. 千万不要为了方便而是用static修饰一个成员变量,只有这个成员变量的数据是需要被共享的时候才使用static修饰。

1. 修饰类方法:

用于修饰类方法(或静态方法),与类变量类似,类方法不需要通过创建对象来使用,可以直接通过类来访问,类方法也不允许被重载。

  1. 非静态的方法只能使用对象调用,不能使用类名调用。
  2. 静态方法可以直接访问静态的成员,但是不能直接访问非静态的成员。
    • 因静态方法可以使用类名调用,而这个时候对象可能还没有存在在内存中,这时候非静态的数据也就不存在在内存中。
  3. 非静态方法可以直接访问静态以及非静态的成员。
    • 因非静态方法必须要由对象调用,如果对象存在了,静态数据以及非静态数据早就存在内存中了。
  4. 静态函数不能出现this以及super关键字。
    • 因静态方法可以使用类名直接调用,而这个时候可能还没有对象存在,this又要代表当前对象。

2. final:

final关键字修饰变量:

被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋初值。

final int MAX_SPEED = 120;

final关键字修饰方法:

该方法不可被子类重写。但是可以被重载。

final void study(){}

final关键字修饰类:

该类不能被继承,即final类不可能有子类。

final class A{}
  1. Java API中有许多类定义为final类,这些类通常是由固定作用、用来完成某种标准功能的类,如Math类、String类、Integer类等。
  2. 容易理解,abstract和final修饰符不能同时修饰一个类,但是可以各自与其他修饰符合用。当一个以上的修饰符修饰类时,这些修饰符之间以空格分开,写在关键字class之前,修饰符之间的先后排列次序对类的性质没有任何影响。
  3. final类中的所有成员变量和方法都认为是final的。

3. 其他修饰符:native、volatile、synchronized等。

5. 抽象方法和抽象类:

1. 抽象方法:

使用abstract修饰的方法,没有方法体,只有声明。定义的是一种规范,就是告诉子类必须要给抽象方法提供具体的实现。

父类中不能有方法体,但是子类必须实现抽象方法。

声明抽象方法的语法如下:

abstract <方法返回值类型> <方法名>([参数列表]);

2. 抽象类:

包含抽象方法的类就是抽象类,通过abstract方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。

1. 抽象类的定义:

抽象类需要使用abstract来修饰,定义语法为:

abstract class <类名> [extends <父类>] [implements <接口名>]{
	<类主体>
}
  1. 抽象类与抽象方法。抽象方法属于一种不完整的方法,只含有声明部分,没有方法主体。
  2. 包含抽象方法的类一定是抽象类,但是抽象类不一定必须包含抽象方法,也可以包含普通方法。也就是说,即使不包含任何抽象方法,也可以将一个类声明为抽象类。
    • 抽象类可以包含普通属性、方法和构造方法。但是构造方法不能用来new实例,只能用来被子类调用。
  3. 抽象类不能被实例化。抽象类不能使用new关键字创建实例化对象。
  4. 抽象类只能用来被继承,抽象方法必须被子类实现。

2. 抽象类的继承:

如果一个类A需要继承抽象类,则该类必须实现抽象类中定义的所有抽象方法。否则,该类也必须修饰为抽象类。也就是说,抽象类的子类如果仅仅实现父类的部分抽象方法,子类也必须声明为抽象类。

6. 接口:

接口(interface)是Java所提供的另一种重要结构。接口是一种特殊的类,但接口与类存在这本质上的区别。类有成员变量和成员方法,而接口却只有常量和抽象方法,也就是说,接口的成员变量必须初始化,同时接口中的所有方法必须声明为abstract方法。

1. 接口的定义:

接口是一种比抽象类还要彻底的一种类(但是与类有着本质区别),接口通过interface来定义,一般形式如下:

[接口修饰符] interface <接口名> [extends [父类接口列表]]{
	接口体
}
  1. 接口修饰符:接口修饰符为接口访问权限,有public和default默认两种类型。
  • public指任意类均可以使用这个接口。

  • default指只有与该接口定义在同一包中的类才可以访问这个接口,而其他包中的类无权访问该接口。

  1. 父类接口列表

一个接口可以继承其他接口,通过关键字extends来实现,其语法与类相同。被继承的类接口被称为父类接口,接口可以实现多继承,当有多个父类接口时,用逗号","分隔。

  1. 接口体
    接口中的属性只能是常量,总是public static final修饰,不写也会默认是静态常量。属性在定义的时候必须用常量初始化。

接口中的方法只能是public abstract。省略的话,也是抽象方法。

2. 接口的实现:

  1. 子类通过implements来实现接口中的规范。一个类可以同时实现多个接口,接口之间用“,”分隔。
  2. 接口不能创建实例,但是可用于声明引用变量类型。
  3. 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。如果一个接口继承了父接口,则必须实现该接口及其父接口的所有方法。
  4. JDK1.7之前,接口只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。JDK1.8之后,接口中包含普通的静态方法。

3. 接口与多重继承:

  1. 与类一样,接口可以使用extends子句生成子接口。原来的接口叫做父接口/基本接口,拓展出的接口叫子接口/派生接口。派生接口不仅保留了父接口的成员,同时也可以加入新的成员以满足实际问题的需要。

  2. 与类不同的是,一个接口可以拓展多个接口,继承他们所有的属性和方法,而一个类只能拓展一个类。显然,接口不能拓展类,接口的方法必须全是抽象的。

  3. interface A extends B{...}

    • 这条语句表示定义了接口A并继承了接口B,使A成为B的子接口,并且具有B的所有属性。接口继承的过程中可能会出现以下情况:
    1. 方法重名:
      • 如果两个方法一样,只保留一个。如果两个方法有不同的参数(类型或个数),那么子接口中包括两个方法,方法被重载;若两个方法仅在返回值上不同,出现错误。
    2. 常量重名:
      • 两个重名常量全部保留,并使用原来的接口名作为前缀。

7. 内部类:

在Java中内部类分为:成员内部类(静态内部类、非静态内部类)、匿名内部类、局部内部类。

1. 成员内部类

可以使用private、default、protected、public任意进行修饰。类文件:外部类$内部类.class

1. 非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

  1. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象,那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
  2. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
  3. 非静态内部类不能有静态方法、静态属性和静态初始化块。
    • 非静态内部类中相当于是一个外部类的成员变量,必须要有外部类的成员才能有内部类成员,所以说不可能有静态的方法属性和初始化块。
  4. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。
  5. 成员变量访问要点:
    1. 内部类里方法的局部变量:变量名
    2. 内部类的成员变量:this.变量名
    3. 外部类属性:外部类.this.变量名

2. 静态内部类:

定义方式:

static class ClassName{
	//类体
}

使用要点:

  1. 当一个静态内部类对象存在,并不一定存在对应的外部类对象。因此,静态内部类的实例方法不能直接访问外部类的实例方法。
  2. 静态内部类看做外部类的一个静态成员。因此,外部类的方法中可以通过:“静态内部类.名字”的方式访问静态内部类的静态成员,通过new静态内部类()访问静态内部类的实例。

2. 匿名类:

使用类创建对象时,Java允许把类体与对象的创建组合在一起。

也就是说,类创建对象时,除了构造方法还有类体,此类体被称为匿名类。如果该类中的方法或属性不会被重复利用,则设计匿名类会比较简单。

匿名类由于无名可用,所以不可能用匿名类声明对象,但是可以直接用匿名类创建一个对象。

匿名内部类:

适合那种只需要一次的类。比如:键盘监听操作等等。

语法:

new 父类构造器(实参列表)\实现接口(){
	//匿名内部类类体
}
  1. 匿名内部类没有访问修饰符。
  2. 匿名内部类没有构造方法。因为他连名字都没有,也就没有构造方法。

3. 局部内部类:

还有一种内部类,他是定义在方法内部的,作用域只限于本方法,成为局部内部类。

局部内部类的使用主要是用来解决比较复杂的问题,像创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。

局部内部类和成员内部类一样被编译,只是他的作用域发生了改变,他只能在该方法中被使用,出了该方法就会失效。

局部内部类在实际开发中应用很少。

8. 泛型类:

JDK5之后支持泛型,泛型是对Java语言的类型系统的一种扩展,支持创建可以按类型进行参数化的类。

泛型的本质是参数化类型,也就是说,所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。

1. 泛型类声明:

首先,在一对尖括号(<>)中声明类型变量,以逗号间隔变量名列表。在类的实例变量和方法中,可以在任何的地方使用这些类型变量。泛型类的声明格式如下:

class 泛型类名<泛型列表>{
	类体
}

泛型类声明时并不指明泛型列表是什么类型的数据,可以是任何对象或接口,但不能是基本类型数据。泛型列表中的泛型可以作为类的成员变量的类型、方法的类型以及局部变量的类型。

泛型类的类体与普通类的类体完全相似,有成员变量和方法构成。例如:

class Chorous<E,F>{
	void makeChorous(E person,F instruments){
		instruments.toString();
		person.toString();
	}
}

其中<E,F>是泛型列表,E和F可理解为一种类参数,声明对象或创建实例时用具体的类名替代。

2. 使用泛型类声明对象:

使用泛型类声明对象时,必须指定类中使用泛型的具体类名。例如:

Chorous<Student,Button> model = new Chorous<Student,Button>();

3. 泛型接口:

与类相同,Java也支持泛型接口,泛型接口的定义格式如下:

interface 泛型接口名<泛型列表>{
	接口体
}

Java泛型的主要目的是可以建立具有类型安全的数据结构,如:链表、散列表等数据结构。使用泛型类建立数据结构时,不必进行强制类型转换。

标签:Java,变量,对象,子类,接口,面向对象,概述,父类,方法
From: https://www.cnblogs.com/guosiliang/p/18037354

相关文章

  • Java基础-面向过程和面向对象
    面向过程和面向对象都是对软件分析、设计和开发地一种思想,它指导着人们以不同的方式去分析、设计和开发软件。这两种思想是相辅相成的。面向过程:使用面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。这个思想适合简单任务,不需要过多......
  • Java基础-常用类
    一、字符串相关的类1.String的特性String类:代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。String是一个final类,代表不可变的字符序列。字符串是常量,用双引号引起来表示。他们的值在创建之后不能更改。String对象的字符内容是存储在一个字符数......
  • java 实现根据word模板生成word文件 word转pdf
    最近做项目要求生成word文件及PDF文件,生成word文件时其中内容要根据不同公司提供的内容动态替换里面的值。参考了很多之后选择用word模板生成word文件。其中主要参考:https://www.cnblogs.com/suzan/p/10577738.html 简单的word模板:https://files.cnblogs.com/files/blogs/8095......
  • 面试题以及一些问题概述
    1数据库三大范式是什么数据库的三大范式是指关系数据库设计中的三个规范化级别,用于规范化数据库中的数据结构,提高数据的一致性和减少数据冗余。这三大范式分别是:1.第一范式(1NF):要求数据库表中的每个字段都是原子性的,不可再分。也就是说,每个字段中的数据不能包含多个值或多个属......
  • Java中使用Graphics2D实现图片添加文字/图片水印
    场景java实现给图片添加水印实现步骤:获取原图片对象信息(本地图片或网络图片)添加水印(设置水印颜色、字体、坐标等)处理输出目标图片。注:博客:https://blog.csdn.net/badao_liumang_qizhi实现1、新建工具类 importorg.apache.commons.lang3.StringUtils;importjavax.im......
  • Java 中 MessageFormat.format 用法
    转载自:https://blog.csdn.net/xiaokui_wingfly/article/details/46124057 查看原文:http://www.ibloger.net/article/139.htmlMessageFormat本身与语言环境无关,而与用户提供给MessageFormat的模式和用于已插入参数的子格式模式有关,以生成适用于不同语言环境的消息。Mes......
  • 高通音频框图概述
    音频框图概述|FrontEndPCMs|SoCDSP|BackEndDAIs|Audiodevices|*************PCM0<------------>**<----DAI0----->CodecHeadset**PCM1<------------>*......
  • java 通过 microsoft graph 调用outlook
    废话不多说一官方文档先看一下官方文档,https://learn.microsoft.com/zh-cn/graph/tutorials/java?context=outlook%2Fcontext&tabs=aad&tutorial-step=1其中的代码,可以通过地址下载:https://developer.microsoft.com/en-us/graph/quick-start 二授权方式microsoft登录授权......
  • Java面向对象之接口和抽象类的区别一目了然
    介绍相信对于Java面向对象部分,很多人很长一段时间对于接口和抽象类的区别,使用场景都不是很熟悉,同是作为抽象层重要的对象,工作中到底什么情况下使用抽象类,不是很清楚。本文就一次性把这些概念一次性说清楚,不用再烦恼了,哈哈!核心概念接口与抽象类最明显的区别可能就是使用上的......
  • java读取resource下的文件 下载
    点击查看代码publicvoiddownloadKsxxYzyTemplate(HttpServletRequestrequest,HttpServletResponseresponse){try{//FileDownloadUtils.downloadFileFromResource(response,YZYMB_NAME,YZYMB_URL);FileDownloadUtils.downloadFileFro......