封装
为什么要封装
在其他的类中可以直接对本类中的属性进行操作,但是还没有办法控制其赋值的内容,为了让将需要用户知道的暴露出来,将不想让用户知道的隐藏,让用户通过自己规定的方法访问.
封装的优点
- 提高代码的安全性:只能通过特定的方式访问
- 提高代码的复用性:方便修改和加入控制语句
- 简化复杂性:封装可以将复杂性封装在类的内部,使得外部代码不需要关心实现的细节,从而简化了外部代码的复杂性。
public class Demo{
private String name; //将类的成员变量访问权限设置为私有
public String getName (){
return name;
}
public void setName(String name){
this.name = name;
}
}
通过不同的权限修饰符使得要给name赋值时只能通过setName方法.还可以在setName方法中加入判断语句,让该方法更加安全.
成员变量和局部变量
继承
定义: 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么,多个类中无需 再定义这些属性和行为,只需要和抽取出来的类构成继承关系.
继承的好处
- 减少冗余,提高代码复用性
- 有利于功能的拓展
- 让类与类之间产生is-a的关系,为多态的使用提供了前提
is-a关系: 猫是 动物
狗是 动物
继承的语法
通过extends关键字,可以声明类B继承另一个类A,格式如下:
[修饰符] class 类A{
}
[修饰符] class 类B extends 类A{
}
类B,称为子类/派生类
类A,称为父类/基类
补充:
- 子类会继承父类所有的实例变量和实例方法
- 子类不能直接访问父类中的私有的(private)成员变量和方法
- Java支持多层继承
- 一个父类可以同时拥有多个子类
- java只支持单继承
- 当一个类没有显示的继承其他类时,默认继承Object类.
方法的重写
- 当父类中的实现不能满足在子类需求时,可以在子类对父类的方法中进行重写,这样调用时,就会调用重写方法.
Override:
是java中的一个注解标签,定义在重写方法上面,表示此方法是从父类重写过来的也可以不添加,只要重写的方法结构与父类方法一致,也算正确的重写.
建议保留:
- 编译器可以进行语言验证
- 阅读代码时,明确此方法时重写
- 注意:构造方法,静态方法不能重写,成员变量不存在重写
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("狗吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
方法重写格式
1. 子类重写的方法必须和父类被重写的方法名称,参数列表相同。
2. 子类重写的方法的返回值类型与父类保存一致。
3. 子类重写的方法使用的访问权限不能小于父类被重写方法的访问权限。
注意:① 父类私有方法不能重写 ② 跨包的父类默认权限的方法也不能重写
4. 子类方法抛出的异常不能大于父类被重写方法的异常
super关键字
在
Java
类中使用
super
来调用父类中的指定操作:
- super可用于访问父类中定义的属性
- super可用于调用父类中定义的成员方法
- super可用于在子类构造器中调用父类的构造器
注意:
尤其当子父类出现同名成员时,可以用
super
表明调用的是父类中的成员
super
的追溯不仅限于直接父类还可以是父类的父类
super
和
this
的用法相像,
this
代表本类对象的引用,
super
代表父类的内存空间
的标识
误区: 不要把super误认为是父类对象,在创建子类对象时,不会创建父类对象.
只会将父类中的信息加载到子类对象中存储
继承中的构造方法
- 子类继承父类时,不会继承父类的构造方法.只能通过“super(形参列表)” 的方式调用父类指定的构造方法.
- 规定super(形参列表),必须声明在构造器的首行. 如果在子类构造器的首行没有显示调super(形参列表),则子类此构造器
- 默认调用super(),即调用父类中空参的构造器.
- 这么做是为了保证先对父类成员进行初始化
开发中常见错误:
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有空参的构造器,则编译出错.
interface接口
通过implements关键字实现接口
- 一个类可以直接继承一个类
- 一个类可以实现多个接口
- 一个接口可以继承多个接口
- 接口中可以定义的内容:
- java8之后可以定义:常量,抽象方法,静态方法,默认方法
- java8之前可以定义:常量,抽象方法
接口与实现类之间存在多态性
接口特性
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别
- 1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
public class Demo1Interface {
/*
接口就是多个类的公共规范.
接口是一种引用类型数据,最重要的内容就是其中的抽象方法.
如何定义一个接口的格式:
public interface 接口名称{
接口内容
}
备注:换成了关键字interface之后,编译生成的字码文件仍是 .java-->.class
*/
/*
接口的使用步骤:
1.接口不能直接使用,必须有一个"实现类"来"实现"该接口
格式:
public class 实现类名称 implements 接口名称{
}
2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法.
实现:去掉abstract关键字,加上方法体大括号
3.创建实现类的对象,进行使用
注意事项:
如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类
*/
public static void main(String[] args) {
//错误写法! 不能直接new接口对象使用
//MyInterFace interFace = new MyInterFace();
//创建类对象使用
MyInterFace interFace = new MyInterfaceDemo();
interFace.method1();
interFace.method2();
}
}
public class MyInterfaceDemo implements MyInterFace{
@Override
public void method1() {
System.out.println("这是第一个方法");
}
@Override
public void method2() {
System.out.println("这是第二个方法");
}
@Override
public void method3() {
System.out.println("这是第三个方法");
}
@Override
public void method4() {
System.out.println("这是第四个方法");
}
}
/*
在任何版本的java中,接口都能定义抽象方法.
格式:
public abstract 返回值类型 方法名称(参数列表);
注意事项:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字,public abstract
2.这两个关键字修饰符,可以选择性的省略.(不推荐)
3.方法的三要素,可以随意定义.
*/
public interface MyInterFace {
//这是一个抽象方法
public abstract void method1();
//这也是抽象方法
public abstract void method2();
//这也是抽象方法
public abstract void method3();
//这也是抽象方法
public abstract void method4();
}
抽象类
使用abstrsct修饰的类就是抽象类一个类中如果包含抽象方法,那么这个类必定是抽象类, 一个类是抽象类他不一定包含抽象方法
特点: 抽象类不能创建对象,其他功能与正常的类想同,可以有成员变量,成员方法,构造方法 主要是在上层定义,让子类继承实现 一个子类如果继承了抽象类,要么重写抽象类中所有的抽象方法,要么将该类也定义为抽象类
多态
- 多态:同一种事物,不同时刻表现不同的状态
- 好处:提高代码复用性
Animal dog = new Dog(); dog.eat(); Animal cat = new Cat(); cat.eat();
- 形式:父类的引用变量 指向了类对象 前提 必须要有继承关系
- 两个不同的时间段: 编译器:写代码时 类型是父类类型
运行期:运行代码时 类型是具体的子类类型
- 多态也称为向上转型,将子类的类型转为父类类型
- 局限性:将子类类型都转化为父类类型,便于程序的扩展
但是也存在问题: 一旦转化为父类类型,就不能调用子类特有的方法,想要使用子类特有的方法,就必须得 向下转型.
final关键字
final 用于修饰类,成员方法,成员变量
- 修饰类,不能被定义为抽象类或是接口,不可被继承
- 修饰方法,子类里不可以重写
- 修饰成员变量是常量
//情况一:类定义时,值就确定了,直接赋值,赋值后值不能改变,所以建于一使用static final static int a =10; //情况二:在类定义时,值不明确,必须在创建对象后,在构造方法中对其进行赋值,每个对象中需要一个常量 final int count; public FinalDemo(){ this.count=10; }public static void main(String[] args) { FinalDemo f= new FinalDemo(10); }
- final修饰的常量定义一般都有书写规范,被final修饰的常量名称,所有字母都大写。