1.面向对象
类和对象的理解
- 类:类是对现实生活中一类具有共同属性和行为的事物的抽象,是对现实事物的一种描述。(例如一个描述人的类,他只描述人的总体特征,有姓名、身高等信息,而没有具体的值)
- 类的组成:成员变量,方法,构造器,代码块,内部类。
- 对象:对象是真实存在的实体,是类的实例。(对类进行实例化,设置具体的值,让我们知道是哪个人以及他的各种身份信息)
客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。
静态变量和静态方法
Java中使用static
修饰的字段的方法被称为静态字段和静态方法,静态变量和静态方法不属于实例而属于类(可以理解为是实例公共属性),可以使用类名.静态属性
和实例变量.静态属性
来访问静态属性
class Person {
public static int age;
public static void speak() {
System.out.println("今年刚满18岁")
}
}
//调用
Person.age = 18;
Person.speak();
成员变量和局部变量
变量位置不同被分为成员变量和局部变量,成员变量在类中方法外,局部变量在方法内部。
成员变量和局部变量的区别:
- 内存中位置不同:成员变量(堆内存)局部变量(栈内存)
- 生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,碎着方法的调用完毕而消失)
- 初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)
构造方法
构造方法是一种特殊的方法,作用专门用来创建对象,主要是完成对象数据的初始化。方法名与类名相同, 使用:Person p = new Person ();
格式:
public class 类名{
修饰符 类名( 参数列表 ) {
. . .
}
}
注意:
构造方法的创建:如果没有定义构造方法,系统将给出一个默认的无参数构造方法,如果定义了构造方法,系统将不再提供默认的构造方法
构造方法的重载:如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
推荐的使用方式:无论是否使用,都手工书写无参数构造方法
代码块
代码块,类似于方法,将逻辑语句封装在方法体中,通过{ }包围起来。但其和方法不同,,只有方法体,且不用通过对象或类显式调用,而是在加载类时或创建对象时被隐式调用。被static修饰的代码块叫静态代码块,作用是对类进行初始化,随着类的加载而执行且只会执行一次。普通代码块,则每创建一个对象就执行一次。
格式:
[static]{
代码
};
- 父子类语句执行顺序:
父类静态代码块 > 子类静态代码块 > 父类普通代码块 > 父类构造方法 > 子类普通代码块 > 子类构造方法
this和super关键字
- this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
- super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
this和super的三种用法
- 普通用法:this关键字代指对象本身,调用自己的成员;super关键字代指父类,用用父类的成员
- 参数名重名:形参与成员名字重名,用 this 来区分;子类中的成员变量或方法与父类中的成员变量或方法同名,使用super关键字区分
- 引用构造函数:this调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句);super调用父类中的某一个构造函数(应该为构造函数中的第一条语句)
权限修饰符
public | protected | 默认 | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中的类 | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:
- 成员变量使用
private
,隐藏细节。 - 构造方法使用
public
,方便创建对象。 - 成员方法使用
public
,方便调用方法。
小贴士:不加权限修饰符,就是默认权限
2.面向对象的特点
2.1 封装
封装是面向对象的一个基础特性,也是面向对象编程的一个重要原则。它指的是将对象的内部属性隐藏起来,并通过公共方法来访问和修改这些状态。这样做的好处是可以控制对对象的访问,防止不合法的状态修改,并提供了一种更加可控的方式来与对象交互。
2.2 继承
子类继承的细节
- 子类不能继承父类的构造方法
- 子类能继承父类的私有成员(变量,方法),但无法直接访问,需要通过getter/setter访问
- 父子类中出现重名的成员属性(变量,方法),需要使用super关键字调用父类属性
- 子类所有构造方法的第一行都会默认先调用父类的无参构造方法
final 关键字
- final修饰的类,不能被继承
- final修饰的方法,不能被重写
- final修饰的变量,只能赋值一次
2.3 多态
多态体现的格式:
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();
多态的运行特点
- 调用成员变量时:编译看左边,运行看左边
- 调用成员方法时:编译看左边,运行看右边
引用类型转换
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型
-
向上转型:多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
使用格式:父类类型 变量名 = new 子类类型();
-
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:
子类类型 变量名 = (子类类型) 父类变量名; 如:Aniaml a = new Cat(); Cat c =(Cat) a;
instanceof关键字
-
作用:如果变量属于该数据类型或者其子类类型,返回true,否则返回false。
-
新特性JDK14的时候提出了新特性,把判断和强转合并成了一行
//新特性 //先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d //如果不是,则不强转,结果直接是false if(a instanceof Dog d){ d.lookHome(); }else if(a instanceof Cat c){ c.catchMouse(); }else{ System.out.println("没有这个类型,无法转换"); }
3.抽象类与接口
抽象类
关键字: abstract
- 抽象类不能创建对象,有构造方法(提供给子类使用)
- 继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类
- 抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。
接口
关键字:interface
- 接口中的抽象方法默认会自动加上public abstract修饰
- 接口中成员变量默认被public static final修饰,必须给初始值,可以直接用接口名访问
- 必须重写实现的全部接口中所有抽象方法。
- 如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类
- 一个类可以同时实现多个接口
注意:JDK1.8接口新特性:
- 默认方法(default method):允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;
- 静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。
4.内部类
4.1 成员内部内
获取成员内部类对象的两种方式:
方式一:外部直接创建成员内部类的对象
外部类.内部类 变量 = new 外部类().new 内部类()
方式二:在外部类中定义一个方法提供内部类的对象
内部类的使用格式:
外部类.内部类
// 访问内部类的类型都是用 外部类.内部类
编写成员内部类的注意点:
- 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等
- 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
- 创建内部类对象时,对象中有一个隐含的Outer.this记录外部类对象的地址值。
4.2 静态内部类
内部类的使用格式:
外部类.内部类。
静态内部类对象的创建格式:
外部类.内部类 变量 = new 外部类.内部类构造器;
调用方法的格式:
- 调用非静态方法的格式:先创建对象,用对象调用
- 调用静态方法的格式:外部类名.内部类名.方法名();
4.3 局部内部类
- 局部内部类 :定义在方法中的类。
4.4 匿名内部类【重点】
概述:匿名内部类是一个隐含了名字的内部类
- 使用场景:通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递
interface Swim {
public abstract void swimming();
}
public class Demo07 {
public static void main(String[] args) {
// 普通方式传入对象
// 创建实现类对象
Student s = new Student();
goSwimming(s);
// 匿名内部类使用场景:作为方法参数传递
Swim s3 = new Swim() {
@Override
public void swimming() {
System.out.println("蝶泳...");
}
};
// 传入匿名内部类
goSwimming(s3);
// 完美方案: 一步到位
goSwimming(new Swim() {
public void swimming() {
System.out.println("大学生, 蛙泳...");
}
});
goSwimming(new Swim() {
public void swimming() {
System.out.println("小学生, 自由泳...");
}
});
}
// 定义一个方法,模拟请一些人去游泳
public static void goSwimming(Swim s) {
s.swimming();
}
}
Lambda表达式
接下来,我们学习一个JDK8新增的一种语法形式,叫做Lambda表达式。作用:用于简化匿名内部类代码的书写
基本使用
(被重写方法的形参列表) -> {
被重写方法的方法体代码;
}
需要给说明一下的是,在使用Lambda表达式之前,必须先有一个接口,而且接口中只能有一个抽象方法。(注意:不能是抽象类,只能是接口)
标签:Java,内部,构造方法,子类,面向对象,父类,方法,public From: https://blog.csdn.net/m0_63758722/article/details/141302197