文章目录
封装
类和对象
类:不管多么复杂的类,只有两部分组成:属性(成员变量)、行为(成员方法)。
类是抽象的,对象是具体的,类的某个具体存在即为对象。
类的定义和使用
定义
public class Person {
String name;
int age;
public void print() {
System.out.println("一个人");
}
}
使用
Person person = new Person(); //new的本质是在调用构造器,创建对象
person.print();//调用成员方法
person.name = "lan";//调用成员变量
使用变量的规则:遵循就近原则
如果局部位置有局部变量就使用;没有则找类的成员变量,有就使用;没有找父类。
构造方法(构造器)
-
修饰符 构造方法名(参数列表) {
};
-
方法名与类名相同,没有返回值,没有返回值类型(void也没有);
-
如果没有自行定义带参数的构造方法,则系统会给出默认无参构造器;
-
如果自行定义带参数的构造方法,且还想使用无参构造器时,必须显式给出无参构造,否则报错;
-
可以重载。
IDEA中的创建构造方法的快捷键:Alt+Insert
继承
子类继承(extends)父类,子类拥有了父类的非私有成员
getXXX()和setXXX()是对外的接口
继承关系中类成员的使用
- 子父类中定义了同名的成员变量,如何使用?
遵循就近原则,局部变量->子类变量->父类变量(public)->Object
this.name :当前类的name属性
super.name :父类的name属性
-
对象初始化顺序:先父类后子类
-
this和super
this 本质:当前对象 从本类中找
super 本质:父类内存空间的标识 从父类开始找
super调用父类的构造方法必须在构造方法的第一个;super必须只能出现在子类的方法或构造方法中;super和this不能同时调用构造方法。
- 子父类中定义了同名的成员方法,如何使用?
就近原则:顺序:本类->父类->…->Object
访问父类方法的方式:super.父类方法名();
定义重名方法的前提:扩展父类功能;重新实现父类功能
方法重写(非静态方法才算重写)
注意实项
- 父类私有方法无法重写
- 子类方法的访问权限(从小到大:private->default(默认)->protected->public)不能小于父类方法的访问权限
- 子类不能比父类方法抛出更大的异常
四大访问权限修饰符
本类 | 本包 | 子类 | 其它类 | |
---|---|---|---|---|
private | √ | |||
default(默认) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
本类 | 同包下的类 | 不同包下的子类 | 不同包下的无关类 | |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
总结:
private:强调的是给自身的类来使用
default:强调的是给同一个包中的类来使用
protected:强调的是给自身类的子类来使用
public:强调的是都能使用
Java中继承的特点
单继承
Java只支持单继承,但是支持多层继承
Java支持接口的多继承
其他特点
- 私有成员不能被继承
- 构造方法不能被继承
- 继承体现了“is a"的关系
补充
package com.opp.demo1;
//父类
public class A {
public static void print() {
System.out.println("A->print");
}//静态方法
}
package com.opp.demo1;
//子类,继承A类
public class B extends A{
public static void print() {
System.out.println("B->print");
}//静态方法
}
package com.opp.demo1;
//测试类
public class Test {
public static void main(String[] args) {
B b = new B();
A a = new B();
b.print();//B->print
a.print();//A->print
}
}
package com.opp.demo1;
//父类
public class A {
public void print() {
System.out.println("A->print");
}//非静态方法
}
package com.opp.demo1;
//子类,继承A类
public class B extends A{
public void print() {
System.out.println("B->print");
}//非静态方法
}
package com.opp.demo1;
//测试类
public class Test {
public static void main(String[] args) {
B b = new B();
A a = new B();
b.print();//B->print
a.print();//B->print
}
}
多态
如何实现多态
三个步骤
- 要有继承关系;
- 要有方法重写;
- 要有父类引用子类对象。
Animal an = new Dog();//父类的引用指向子类,如果是静态同名不算重写
多态中调用成员方法是:编译看左,运行看右(非静态)
多态的应用场景
父类可以作为形参的数据类型,这样可以接收其任意的子类对象
多态中成员变量的使用
- 子父类中定义了同名的成员变量,如何调用?
成员变量不能重写,遵循编译看左,运行看右
多态的好处和弊端
弊端
不能访问子类的特有成员
好处
可进行类型转换
- 向上转型(自动类型转换)
Animal an = new Dog();//父类->子类
- 向下转型(强制类型转换)
Dog dog = (Dog)an;//子类->父类
注意事项
- 只能在继承层次内进行转换,否则出现异常(ClassCastException);
- 将父类对象转换成子类前,使用instanceof进行检查
Animal an = new Dog();
if(an instanceof Dog) {
Dog dog = (Dog)an;
dog.watch();
}
抽象类
包含抽象方法的类,用abstract修饰
-
public abstract class Animal { public abstract void eat(); }
-
特点
(1)必须用abstract修饰,不能被实例化,其子类可以重写父类所有抽象方法或者定义成抽象类
(2)抽象类成员变量的特点:
可以有普通的成员变量,也可以有成员常量
(3)抽象类成员方法的特点:
可以有普通方法
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
(4)抽象类构造方法的特点:
有构造方法,且可以重载
final关键字
作用
- 修饰类:不能被继承,但是其本身可以继承其他类;
- 修饰方法:该方法不能被重写,不能与abstract共用;
- 修饰变量:最终变量,即常量(通常字母大写)。
static关键字
作用
- 修饰类的成员:
成员变量:类变量
成员方法:类方法
- 调用方式
类名.成员变量名;
类名.成员方法名(参数);
static修饰成员变量
特点:被本类所有对象共享
例如:
final static String departmentName = "研发部";//用final修饰后不能被修改
static修饰成员方法
修饰后为静态方法,静态方法没有this,所以不能访问非静态成员
使用场景:只需访问静态成员,不需要访问对象状态,所需参数由参数列表显示提供
接口
接口的定义
interface 接口名{}
类和接口是实现关系,用implements
class 类名 implements 接口名
接口创建对象的特点
- 接口不能实例化;
- 接口的实现类可以是抽象类也可以是普通类。
接口继承关系的特点
接口可以多继承其他接口
接口体现的是“like a”,定义扩展功能,而继承体现的是“is a",父类中定义共性内容
接口成员变量的特点
接口没有成员变量,只有公有的,静态的常量
(public static final)常量名 = 常量值;//括号内可以写可以不写
接口成员方法的特点
- JDK7以前,公有的抽象的方法
(public abstract)返回值类型 方法名();//括号内可以不写
- JDK8以后,可以有默认方法和静态方法
public default 返回值类型 方法名();
- JDK9以后,可以有私有方法
private 返回值类型 方法名();
接口没有构造方法