类与对象
类
- java中要想创建对象,必须先要有类的存在。
- 类指的是一组相关属性和行为的集合,我们将其理解为是一张对象的设计图
类的组成
- 属性:成员变量,跟之前定义变量的格式一样,只不过位置需要放在类中方法外。
- 行为:成员方法,跟之前定义方法的格式一样,只不过需要去掉
static关键字。
代码示例
public class Person {
private int age;
private String name;
public void eat() {
System.out.println("吃饭");
}
}
成员变量和局部变量
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中位置不同 | 方法外 | 方法内 |
| 初始化值不同 | 有默认的初始化值 | 没有,使用之前需要完成赋值 |
| 内存位置不同 | 堆内存 | 栈内存 |
| 生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行结束而消失 |
| 作用域 | 在自己所归属的大括号里面 | 在自己所归属的大括号里面 |
this关键字
this代表当前类对象的引用(地址)
构造方法
构造器
- 初始化一个新建的对象
- 构建、创造对象的时候所调用的方法
格式
- 方法名与类名相同,大小写也一样
- 没有返回值类型,连void都没有
- 没有具体的返回值类型(不能由retrun带回结果数据)
执行时机
- 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
- 不能手动调用构造方法
构造方法的作用
- 本质作用:创建对象
- 结合构造方法执行时机:给对象中的属性(成员变量)进行初始化
构造方法的注意事项
- 构造方法的创建
- 如果没有定义构造方法,系统将会给出一个默认的无参构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法
- 构造方法重载
- 构造方法也是方法,也可以重载
- 推荐使用方式
- 无参构造方法,和带参构造方法,都手动自己给出
代码示例
public class Person {
private int age;
private String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
class Demo{
public static void main(String[] args) {
Person bob = new Person(20, "bob");
}
}
static关键字
static关键字介绍
static是静态的意思,可以修饰成员变量,也可以修饰成员方法。
static修饰成员的特点
- 被其修饰的成员,被该类的所有对象共享
- 多了一种调用方式,可以通过类名调用
- 随着类的加载而加载,优先于对象存在
static用途
- static修饰成员变量:共享数据
- static修饰成员方法:常用于工具类
static注意事项
- static方法中,只能访问静态成员(直接访问)
- static中不允许出现this关键字
继承
继承介绍
继承:让类与类之间产生关系(父子关系),子类可以直接使用父类中的非私有的成员
什么时候使用继承?
当类与类之间,存在相同(共性)的内容,并且产生了 is a 的关系,就可以考虑使用继承,来优化代码。
继承中成员的访问特点
- 成员变量:子父类中,如果出现了重名的成员变量,使用的时候根据就近原则,优先使用子类的。要想使用父类的通过super关键字进行解决
- 成员方法:父类中私有的方法不能被重写,子类重写父类的方法时,访问权限必须大于等于父类
- 构造方法:在所有的构造方法中,都默认隐藏了一句话super();通过这句代码,来访问父类的空参构造方法
权限修饰符
| 权限修饰符 | 不同包的无关类 | 不同包的子类 | 同一个包中 | 同一个类中 |
|---|---|---|---|---|
| public | Y | Y | Y | Y |
| protected | N | Y | Y | Y |
| 默认 | N | N | Y | Y |
| private | N | N | N | Y |
this和super
- this:代表本类对象的引用
- super:代表父类存储空间的标识
注意:this()和super()都在争夺构造方法的第一行的位置,所以二者不能共存。
java继承特点
java只支持单继承,不支持多继承,但支持多层继承。
final关键字
final关键字标识最终的意思,可以修饰类、方法、变量
final修饰的特点:
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰类:表明该类是最终类,不能被继承
- 修饰变量:表明该变量是常量,不能再次赋值
final修饰变量的细节补充:
- 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
- 变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
- 成员变量如果被final修饰,需要在构造方法结束之前完成赋值
包
- 包本质来说就是文件夹,用来管理文件的
- 建包的语法格式:package 公司域名倒写.技术名称。包名建议全部英文小写,且具备意义
- 建包语句必须在第一行,一般idea工具会帮助创建
导包
- 相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!导包格式:import 包名.类名;
- 假如一个类中需要用到不同类,而这两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
抽象类
抽象类是一种特殊的父类,内部可以编写抽象方法
抽象方法
- 抽象方法:将共性的行为(方法)抽取到父类之后,发现该方法的实现逻辑无法在父类中给出具体明确,该方法就可以定义为抽象方法
- 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。
抽象类和抽象方法定义格式
public abstract class 类名 {}
public abstract 返回值类型 方法名(参数列表);
注意事项
- 抽象类不能实例化
- 抽象类存在构造方法
- 抽象类中可以存在普通方法
- 抽象类的子类
- 要么重写抽象类中的所有抽象方法
- 要么子类是抽象类
abstract关键字的冲突
- final:被abstract修饰的方法,强制要求子类重写,被final修饰的方法子类不能重写
- private:被abstract修饰的方法,强制要求子类重写,被private修饰的方法子类不能重写
- static:被static修饰的方法可以类名调用,类名调用抽象方法没有意义
接口
体现的思想是对规则的声明,java中的接口更多体现的是对行为的抽象
- 接口用关键字interface来定义:public
interface接口名{} - 接口不能实例化
- 接口和类之间是实现关系,通过implements关键字来表示
- public class 类名 implements 接口名{}
- 接口的子类(实现类)
- 要么重写接口中的所有抽象方法
- 要么是抽象类
接口中的成员特点
- 成员变量:只能是常量,默认修饰符是public static final
- 构造方法:没有
- 成员方法:只能是抽象方法,默认修饰符public abstract,关于接口中的方法,jdk8和jdk9中有一些新特性
类和接口之间的各种关系
- 类和类的关系:继承关系,只能单继承,但是可以多层继承
- 类和接口的关系:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
- 接口和接口的关系:继承关系,可以单继承,也可以多继承
抽象类和接口的区别
- 成员变量:
- 抽象类:可以定义变量,也可以定义常量
- 接口:只能定义常量
- 成员方法:
- 抽象类:可以定义抽象方法,也可以是具体方法
- 接口:只能定义抽象方法
- 构造方法:
- 抽象类:有
- 接口:没有
抽象类和接口的对比
- 抽象类:是事物做抽象(描述事物)
- 接口:对行为抽象(制定规则)
多态
同一个行为具有多个不同表现形式或形态的能力
多态前提
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
多态的成员访问特点
- 成员变量:编译看左边(父类),执行看左边(父类)
- 成员方法:编译看左边(父类),执行看右边(子类)
多态的好处和弊端
- 多态的好处:提高了程序的扩展性
- 对象多态:将方法的形参定义为父类类型,这个方法可以接收该父类的任意子类对象。
- 行为多态:同一个行为,具有多个不同表现形式或形态的能力
- 多态的弊端:不能使用子类的特有成员
多态中的转型
- 向上转型:从子到父(父类引用指向子类对象)
- 向下转型:从父到子(将父类引用所指向的对象,转交给子类类型)
多态中的转型问题
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
- 关键字:instanceof
- 使用格式:
- 对象名 instanceof 类型
- 判断一个对象是否是一个类的实例
- 通俗的理解:判断关键字左边的对象,是否是右边的类型,返回boolean类型结果
接口新特性
- jdk8的新特性:接口中可以定义有方法体的方法。(默认、静态)
- jdk9的新特性:接口中可以定义私有的方法。
jdk8接口特性
允许在接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法就是默认方法,作用:解决接口升级的问题
接口中默认方法的定义格式:public default 返回值类型 方法名(参数列表){}
注意事项:
- 默认方法不是抽象方法,所以不强制被重写(但是可以被重写,重写的时候去掉default关键字)
- public 可以省略,defalut不能省略
- 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写。
允许在接口中定义static静态方法
接口中静态方法的定义格式:public static void show(){}
注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省略,static不能省略
jdk9接口新特性
接口中允许定义private私有方法
接口中静态方法的定义格式:
- 格式1:private 返回值类型 方法名(参数列表){}
- 格式2:private static 返回值类型 方法名(参数列表){}
代码块
在java类下,使用{}括起来的代码被称为代码块
分类:
- 局部代码块
- 位置:方法中定义
- 作用:限定变量的生命周期,及早释放,提高内存的利用率
- 构造代码块
- 位置:类中方法外
- 特点:每次构造方法执行的时候,都会执行该代码中的代码,并且在构造方法执行前执行
- 作用:将多个构造器方法中相同的代码,抽取到构造代码块中,提高代码的复用性
- 静态代码块
- 位置:类中方法外定义
- 特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
- 作用:在类加载的时候做一些数据初始化的操作。
- 同步代码块
内部类
内部类就是定义在一个类里面的类,封装性更好
public class Outter {
class inner {
}
}
创建对象的格式:外部类类名.内部类类名 变量名=new 外部类对象().new 内部类对象();
Outter.inner inner = new Outter().new inner();
内部类成员访问
- 内部类,访问外部类成员:直接访问,包括私有的。
- 外部类中,访问内部类成员:需要创建对象访问
- 在成员内部类中访问所在外部类对象,格式:外部类名.this
分类
成员内部类
静态内部类:有static修饰的成员内部类
public class Outer {
static class Inner {
}
}
class Demo {
public static void main(String[] args) {
//静态内部类创建格式
//外部类名.内部类名 对象名=new 外部类类名.内部类对象();
Outer.Inner inner = new Outer.Inner();
}
}
局部内部类:放在方法,代码块,构造器等执行体中。鸡肋语法,了解即可
匿名内部类:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部),前提:需要存在一个接口或类,匿名内部类可以作为方法的实际参数进行传输
//匿名内部类可以使代码更加简洁,定义一个类的同时对其进行实例化
new 类名/接口(){}
Lambda表达式
- lambda表达式是jdk8开始后的一种新语法形式。
- 作用:简化匿名内部类的代码写法
格式
()->{}
(匿名内部类被重写方法的形参列表)->{ 被重写方法的方法体代码。 }
注意:lambda表达式只能简化函数式接口的匿名内部类的写法形式
什么是函数式接口?
- 首先必须是接口,其次接口中有且仅有一个抽象方法的形式
- 通常我们会在接口上加上一个@FunctionlInterface注解,标记该接口必须是满足函数式接口。
lambda表达式的省略写法
- 参数类型可以省略不写。
- 如果只有一个参数,参数类型可以省略,同时()也可以省略。
- 如果lambda表达式的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号,此时,如果这行代码是return语句,必须省略return不写,同时也必须省略“;”不写
lambda表达式和匿名内部类的区别
- 使用限制不同
- 匿名内部类:可以操作类,接口。
- lambda表达式:只能操作函数式接口
- 实现原理不同
- 匿名内部类:编译之后,会产生一个单独的.class字节码文件
- lambda表达式:编译之后,没有一个单独的.class字节码文件