面向对象知识汇总
1.面向过程和面向对象的设计思想
面向过程(缩写POP):
- 分析出解决问题所需要的步骤,然后按步骤一步一步实现;
- 面向过程直接关注流程/过程。
面向对象(缩写OOP):
- 以分类的方式进行思考和解决问题;
- 面向对象先对整体进行分类,然后根据不同的类深入细节的处理;
- 面向对象的思想符合人类的认知习惯。
两者间的关系:
面向对象无法取代面向过程。面向对象是从宏观上把握事物之间的关系,在具体到如何实现某个细节时,仍然采用面向过程的思维方式。面向对象如果离开了面向过程,就无法实现真正的落地,成为无源之水。
2.Java类
什么是类?
- 类是一个模板,它是描述一类事物(集体的对象,具体的存在)的属性和行为的集合;
- 类是表示一个客观世界某类群体的一些基本特征抽象;
- 类是一个模板,是对同一类事物(对象)的共同属性、特征进行定义,把这些信息创建一个文件(.java 类)记录下来。
类的结构:
- 成员变量:事物属性的描述;
- 方法:事物的行为(可以做的事情);
- 构造方法:用于创建对象;
- 内部类:即在类体中声明的类;
- 块:一段没有名称的代码块。
3.java类的定义
- 第一步:发现类
- 第二步:发现类的共有属性(成员变量)
- 第三步:发现类的方法
/*
第一步: 发现类
类的声明格式:
[访问权限修饰符] [修饰符] class 类名{
成员变量:事物属性的描述;
方法:事物的行为(可以做的事情);
构造方法:用于创建对象;
内部类:即在类体中声明的类;
块:一段没有名称的代码块;
}
访问权限修饰符:public,无(默认)
修饰符: final,abstract...
关键字class用来定义一个类
java类名的命名规范:
类名首字母大写,见名知意,驼峰表示
*/
public class Car {
/*
第二步:发现类的共有属性(成员变量)
类的属性
成员变量:定义在类中的变量
声明成员变量的格式:
[访问权限修饰符] [修饰符] 数据类型 成员变量名 [= [值] ];
*/
String name;//名称
String color;//颜色
float price;//价格
/*
第三步:发现类的方法
方法声明格式:
[访问权限修饰符] [修饰符] [返回值类型] 方法名(参数类型 参数值){
语句块;
[return 返回值;]
}
*/
public void start(){
System.out.println("汽车启动。");
}
public void stop(){
System.out.println("汽车停止。");
}
}
4.Java对象
对象是以类(汽车类…)为模板,在内存中创建一个具体存在的实例(实实在在存在的、可以被使用的)。
public class testCar {
public static void main(String[] args) {
/*
Car bm = new Car();
new Car():使用 new + car类构造方法,在内存中创建一个具体的汽车对象
Car bm: 以Car类为类型,声明一个变量 bm,让bm变量指向(引用)内存中的对象
通过使用 bm 变量来访问对象中的成员变量和成员方法;
*/
Car bm = new Car();
bm.name = "宝马";
bm.color = "蓝色";
bm.price = 300000;
bm.start();
bm.stop();
System.out.println(bm.name+"||"+bm.color+"||"+bm.price);
Car bsj = new Car();
bsj.name = "保时捷";
bsj.color = "红色";
bsj.price = 800000;
bsj.start();
bsj.stop();
System.out.println(bsj.name+"||"+bsj.color+"||"+bsj.price);
}
}
5.变量分类
按照位置变量分为:
成员变量:
- 成员变量是定义在类中,方法体之外的变量。
- 成员变量可以使用java中支持的所有的数据类型。
- 可以不进行初始化赋值,在创建对象时,虚拟机会自动为其赋值。
- 在成员方法中可以访问成员变量。
- 成员变量在创建对象的时候会从类中复制一份到对象中。
局部变量:
- 在方法、构造方法或者语句块中定义的变量被称为局部变量。
- 局部变量可以使用java语言中任何一种数据类型。
- 局部变量在使用前必须初始化赋值。
- 变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
6.方法分类
成员方法:
成员方法是定义在类中。必须通过对象调用。
/*
方法声明格式:
[访问权限修饰符] [修饰符] [返回值类型] 方法名(参数类型 参数值){
语句块;
[return 返回值;]
}
*/
public void start(){
System.out.println("汽车启动。");
}
public void stop(){
System.out.println("汽车停止。");
}
构造方法:
作用:用来创建对象的方法。
特点:
- 构造方法名与类名相同,且没有返回值,且不需要使用void修饰;
- 每个类中都有构造方法。如果没有显式地为类定义构造方法,java中会默认有一个无参的构造方法;
- 也可以定义有参数的构造方法,一旦定义了有参数的构造方法,默认的无参构造方法就会失效,如果还需要使用默认的无参构造方法,必须显式地声明;
- 一个类中可以有多个构造方法,通过方法的参数区分。
/*
构造方法
*/
public Car(){
System.out.println("无参的构造方法");
}
public Car(String n){
name=n;
System.out.println("有参数的构造方法");
}
public Car(String n,String c){
name=n;
color=c;
System.out.println("有参数的构造方法");
}
7.方法的重载(overload)
在同一个类中,出现多个方法名相同的现象。-------方法的重载
方法名相同时,通过参数区分:
- 参数的个数;
- 参数的类型;
- 参数的顺序;
构造方法、成员方法都可以重载。
8.对象与引用
Java语言中除基本类型之外的变量类型都称之为引用类型。
Java中的对象是通过引用对其操作的。
Car bm = new Car();
/*
通常把这句语句的动作称之为创建一个对象,创建一个对象,类加载一次。
①“new Car()”:使用 new + Car类构造方法,在内存中(堆空间)里创建一个具体的Car对象;
②“Car bm”:以Car类为类型,声明一个变量bm,让bm变量指向(引用)内存中的对象;
③通过使用bm变量来访问对象中的成员变量和成员方法。
*/
基本类型和引用类型的区别
基本类型:
byte,short,int,long,float,double,char,boolean
它的值就是一个数字,一个字符或一个布尔值。
引用数据类型:
类,接口,数组
它的值是对象在内存空间中的地址,具体的对象存在堆中。
值传递与引用传递
Java中进行方法调用中传递参数时,参数传递有两种:
值传递:(形参数类型是基本数据类型)方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
引用传递:(形参数类型是引用数据类型参数)也称为传地址。方法调用时,实际参数是对象,这是实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
基本类型传递的是该数据值本身。引用类型传递的是对对象的引用,而不是对象本身。
9.static 关键字
static属性,即静态属性,可以用来修饰类的属性(成员变量),方法,代码块,内部类。
用static修饰的成员变量可以称为 静态(类)变量,类只有一份,static修饰的变量也只有一份。
- 随着类的加载而加载;
- 优先于对象存在;
- 修饰的成员,被所有对象所共享;
- 可不创建对象,直接被类调用。
static方法可以使用对象调用,也可以直接用类名调用,建议用类名直接调用。
在static方法内部只能访问类的static属性,不能访问类的非static属性,static属性先加载。
package day10;
public class Chinese {
/*
static 关键字
关键字:被语言赋予特定含义的单词 都是小写
static 静态的,可以用来修饰类的属性,方法,代码块,内部类
随着类的加载而加载
优先于对象存在
修饰的成员,被所有对象所共享
可不创建对象,直接被类调用
*/
String name;
int age;
String address;
static String country="中国";
//成员方法中可以访问 成员变量 及 静态变量
public void getMethod(){
System.out.println(name);
System.out.println(country);
}
/*
static 修饰方法
static方法可以使用对象调用,也可以是直接用类名调用,建议用类名直接调用
在static方法内部只能访问类的static属性,不能访问类的非static属性,static属性先加载。
*/
public static void getstatic(){
// System.out.println(name); //静态方法中只能访问静态变量 随着类的加载而加载 优先于对象存在
System.out.println(country);
}
}
10.代码块
代码块在类中声明,类似一个没有名称的方法体(代码块),代码块分为实例块和静态块。
public class Demo {
static double PI=3.14;
/*
实例块:每次创建对象时自动调用
*/
{
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
/*
静态块:类加载时自动调用,仅一次,与是否创建对象无关。
*/
static{
System.out.println("静态代码块1");
}
static{
System.out.println("静态代码块1");
}
public static void main(String[] args) {
// new Demo();//创建对象 类加载一次
// new Demo();
System.out.println(Demo.PI);//使用类中静态变量 ,类加载一次
new Demo();
}
11.类的加载执行
static修饰的静态属性/方法先于成员属性/方法执行。
12.包
概念:包就是文件夹
作用:避免类重名;
按照不同功能管理类;
控制访问权限
注意:
包可以更好得管理逻辑相关的类,可以控制不同包之间的访问权限;
导入外部包的类,关键字"import"
/*
package 包路径
*/
package day11;
/*
import 类的地址
在一个类中使用另一个包中的类,需要通过import关键字,将类的地址导入进来
不允许导入两个类名相同的类
注:java.lang 包中的类在使用时不需要导入
*/
import java.util.Date;
//import java.sql.Date;
/*
全类名(唯一的名称) = 包名 + 类名的简称
*/
public class Demo {
public static void main(String[] args) {
Date d = new Date() ;
java.sql.Date date=new java.sql.Date(10);
}
}
13.访问权限修饰符
Java语言中有四个访问权限修饰符,权限由大到小依次为:
①public:公共权限 修饰类、属性、方法。 可以被任意类访问。
②protected:受保护的权限 修饰属性、方法。 可以被同包类访问,如果不是同包类,必须是该类的子类(extends)才可以访问 。
③default(通常不写出来):默认/同包/包权限 修饰类、属性、方法。 只能被同包的类访问
④private:私有权限 修饰属性、方法、内部类。 只能在本类中访问。
14.面向对象语言的三大特征
封装:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
封装的好处:
- 只能通过规定方法访问;
- 隐藏类的实现细节;
- 方便修改实现;
- 方便加入控制语句。
具体表现:
- 需要隐藏的信息(私有属性)使用private权限
- 为私有属性提供专门的操作和访问方法使用public权限
this关键字:
this关键字代表自身类的对象(注意:this关键字必须放在非静态方法里面)
在一个类的方法或构造方法内部,可以使用“ this.成员变量名”这样的格式来引用成员变量名,常常用来区分同名的成员变量和局部变量
package day12;
public class Person {
/*
通过访问权限修饰符private来隐藏一些信息
*/
private String name;
private int age;
/*
为隐藏的信息,提供专门的方法来操作和访问
this关键字代表自身类的对象
使用this关键字引用成员变量
使用this关键字引用成员方法
*/
public void setName(String name){
if(name.length()<5){//名字长度小于5
this.name=name;
}
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
}
继承:
继承是面对对象语言的一种设计思想。
继承是从已有的类(父类/基类)中派生出新的类(子类),新的类(子类)拥有已有类(父类/基类)的一些功能(属性和方法),并能扩展新的能力。
优点:提高代码的可重用性(子类可以使用父类的一些功能)
提高代码的可扩展性(子类可以有自己的功能)
- 在Java中使用 extends 关键字来表示继承关系。
- Java不支持多继承,单继承是Java的继承关系很简单,一个类只能有一个直接父类。
- 继承之后子类可以调用父类的所有非私有属性和非私有方法。
继承的形式:
[访问权限修饰符] [修饰符] 子类名 extends 父类名 { 子类体 }
例:
父类 Animals 如下:
package day12;
/*
父类(基类)
把动物相关的共有的属性、行为,定义在Animals类
当一个没有继承任何一个类时,jvm会默认让类继承Object类
Object是 java为所有类提供的基类(父类) 超类
*/
//public class Animals {
public class Animals extends Object {
private String name;
private int age;
public Animals() {
System.out.println("Animals类无参的构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//成员方法:吃
public void eat(){
System.out.println("动物干饭");
}
}
子类 Dog 如下:
package day12;
/*
Dog类继承Animals类
extends关键字
Dog类是 Animals类的子类, Animals类是Dog类的父类
Dog类是 Animals类的派生类, Animals类是Dog类的基类
java中一个类只能直接继承一个类
*/
public class Dog extends Animals {
//子类扩展自己的功能
private String breed;//品种
public Dog() {
System.out.println("dog类无参的构造方法");
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
//成员方法:狗叫
public void wangwang(){
System.out.println("狗子叫");
}
}
继承的传递性:
C类从B类继承,B类又从A类继承
那么C类就具有B类和A类的所有非私有属性和非私有方法
继承中的构造方法:
- 在创建子类对象时,同时会先创建父类对象;
- 在调用子类构造方法时,先会调用父类的构造方法;
- 子类构造方法总是先调用父类构造方法,默认情况下,调用父类无参构造方法;
- 可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法,如果用super,必须写在构造方法的第一句。
super关键字:
super关键字代表父类的引用。
用途:
- 在子类构造方法中要调用父类的构造方法,需要注意,super语句只能出现在子类构造方法体的第一句;
- 用“ super.成员变量名”来引用父类成员变量;
- 用“ super.方法名(参数列表)”的方式访问父类的方法。
- 与this的区别:this通常指代当前类,super通常指代当前类的父类。
多态:
同一种事物,在不同时刻表现不同的状态。
多态存在的三个必要条件:
- 要有继承关系;
- 要有方法重写;
- 父类引用指向子类对象。
Animals dog= new Dog();// Animals的引用指向Dog的对象
/*
编译看左边,运行期间看右边
当编译期类型是父类,运行期类型是子类时,被称为父类引用指向子类对象。
15.方法的重写(OverRide)
当子类中的成员方法的实现方式与父类中的成员方法的实现方式不同时,可以在子类中将父类中的方法重写(覆盖、复写)
前提:要有继承关系。
重写要求:
- 子类方法的结构(返回值 参数)与父类相同;
- 子类重写后的访问权限必须大于等于父类中的访问权限。
package day12;
/*
XiaoTianQuan类继承Dog类
Dog类继承Animals类
*/
public class XiaoTianQuan extends Dog {
/*
在调用子类构造方法时,先会调用父类的构造方法
*/
public XiaoTianQuan() {
// super(); 构造方法的第一行默认使用super();调用父类默认无参的构造方法
super();//如果要现实的调用,必须放在构造方法的第一行,先确保父类构造方法的调用
System.out.println("XiaoTianQuan类无参的构造方法");
}
/*
方法的重写(OverRide)
当子类中的实现方式与父类中的实现方式不同时,可以在子类中将父类中的方法重写(覆盖、复写)
super放到成员方法中,表示当前类的父类对象,在子类中可以通过super访问父类中成员
@Override 注解(类似于标签)
表示此方法是从父类中重写来的
*/
//重写eat方法
@Override
public void eat() {
System.out.println("哮天犬除了屎啥都能吃");
super.eat();
}
public static void main(String[] args) {
/*
继承的传递性:
*/
XiaoTianQuan xtq= new XiaoTianQuan();
xtq.eat();
}
}
16.类之间的关系——关联,依赖
关联关系:
对象和对象之间的连接。在java中,关联关系的代码表现形式为一个类作为另一个类的属性类型存在。
关联关系分为 单向关联 和 双向关联。
- 单向关联:A类关联B类。
- 双向关联:A类关联B类,B类关联A类。
关联关系的多重性:
- 一对一关联:一个手机号,只能有一位用户。
- 一对多关联:一位用户,可以有多个手机号。
解决一对多的关联的方案:
- 集合
- 数组
依赖关系:
指一个类A使用到了另一个类B
依赖关系的特性:
这种关系具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
依赖与关联:
A类关联B类,指的是B类对象作为A类的属性存在。
A类依赖B类,指的是B类对象作为A类的方法参数存在。
package day12;
public class Person {
/*
通过访问权限修饰符private来隐藏一些信息
*/
private String name;
private int age;
/*
类之间的关系——关联,依赖
关联关系
对象与对象之间的连接。在java中,关联关系的代码表现形式为一个类做为另一个类的属性类型存在。
分为:单向关联 和 双向关联
关联关系的多重性:一对一关联、一对多关联
*/
//Mobile类右
private Mobile mobile;//双向关联、一对一关联
private Mobile[] mobiles;//一对多关联
/*
依赖关系
指一个类A使用到了另一个类B
*/
public void feedAnimals(Dog dog){
dog.setName("妞妞");
System.out.println("喂妞妞");
}
}
17.抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其他功能依然存在。
用abstract修饰的类就是抽象类。
抽象类不一定有抽象方法,有抽象方法,那么这个类必定是抽象类。
抽象类只能用作基类,表示的是一种继承关系。
一个类继承抽象类,要么将子类声明为抽象类,要么重写抽象类中所有的抽象方法。
抽象方法:
- 一种特殊的方法,只有定义/声明,没有实现。
- 被abstract关键字修饰,没有方法体,只是作为方法体的定义。
- 例如: public abstract void eat();//定义一个eat抽象方法
package day12.stractDemo;
/*
被 abstract修饰的类就是抽象类
抽象类不一定有抽象方法
有抽象方法,那么这个类必定是抽象类
*/
public abstract class Animals {
private String name;
public Animals() {
System.out.println("Animals");
}
/*
在顶层类中,方法的实现与子类大多不相同,南无在顶层类中可以将方法声明为抽象方法
被abstract修饰,没有方法体
只作为方法的定义
*/
public abstract void eat();
public abstract void sleep();
}
18.接口
理解为一个纯粹的抽象类,在接口中定义抽象方法。
接口的定义:使用interface关键字用来声明一个接口。
[访问修饰符] interface 接口名称 [extends 其他的接口名1,….其他的接口名n] {
// 声明常量
// 抽象方法
}
接口存在的意义:
- Java中不支持多继承;
- Java中一个类只有一个父类,所以用接口可以实现多继承的逻辑。
接口的特性:
- 常作为类型使用
- 接口不可以被实例化(无构造方法)
- 实现类必须重写接口的所有方法
- Java中的多继承
-
实现类可以实现多个接口
-
接口中的变量都是静态常量
-
多个类可以实现同一个接口
-
一个类可以实现多个接口,但只能继承一个类
-
一个接口能继承其他多个接口
3.接口中是隐式抽象的,当使用一个接口时的时候,不必使用abstract关键字。
4.接口中每一个方法是隐式抽象的,默认为:public abstract
5.接口中声明的属性默认为: public static final
6.接口不是被类继承了,而是被类实现。
7.当类实现接口的时候,类要实现接口中所有的方法。否则,累必须声明为抽象的类。
8.接口与实现类之间存在多态性。接口不能实例化对象(无构造 方法),但可以声明对象的引用。(多态性)
接口的使用:
类使用implements关键字实现接口。在类声明中,implements关键字放在class声明后面。
[访问修饰符] class 类名 implements 接口名1,接口名2……{
}
结合继承:
[访问修饰符] class 类名 extends 父类名 implements 接口名1,接口名2……{ }
代码示例:
package day13;
//interface 关键字修饰接口
/*
接口与接口的关系:
接口继承接口 一个接口可以继承多个接口
*/
public interface Animal extends InterfaceA,InterfaceB {
/*
接口:
理解为一个纯粹的抽象类, 在接口中定义抽象方法
*/
/*
接口定义的成员变量是一个常量,默认被 public static final 修饰
*/
// public static final int num = 10;
int num = 10;
/*
jdk8以后接口中声明的抽象方法默认被 public abstract 修饰
*/
public abstract void eat();
void sleep();
/*
jdk8以后加入静态方法,默认方法
*/
public static void play(){
}
//默认方法
public default void keep(){
}
}
19.final关键字
final关键字修饰属性、方法、类、方法参数。
/*
final 关键字 可以修饰 类,属性,方法,方法参数
final修饰的类 不能被继承
*/
//public final class FinalDemo {
public class FinalDemo {
/*
final修饰的变量变为常量 ,值不能改变
① 直接赋值
② 通过构造方法传进来一个值
*/
final static int num = 10;//final修饰的变量直接赋值 通常再用static修饰 ,在内存中 的方法区中 只有一份
// final int count; //final修饰的变量 通过构造方法进行赋值
// public FinalDemo() { //无参的构造方法 出现时 此时有final修饰的变量需要通过构造方法进行赋值 ,所以final修饰的变量会报错
// }
// public FinalDemo(int a){ //有参数的构造方法,同时传进来一个值赋给final修饰的变量
// count = a;
// }
/*
final修饰的方法,不能被子类重写
*/
public final void eat(){
System.out.println("玩的好");
}
/*
final 修饰的方法 ,值不能改变
*/
public void test(final int a){
// a=5;//报错,传进来的a本身就有值,不能再给a赋值
System.out.println(a);
}
}