一、封装
例:插线板,使用者只需要知道插上插座电器可以工作即可,至于内部线路如何连接,不需要了解
例:组装电脑,电脑箱外部提供插线的口,但是对使用者来说并不需要了解机箱内部的部件怎么连接的。
1.1 封装的概念
什么是封装:在类中,对于不想被类外直接访问的成员,进行私有化,同时对外提供一个共有的方法为了访问私有的成员
1.2 private
使用private访问权限实现成员的私有化,private修饰的成员就是私有成员,只能在类内部直接访问,类外不能直接访问
1.3 get和set方法
get方法表示访问私有属性的方法:
语法:
public 属性类型 getXx(){
return 属性;
}
set方法表示修改私有属性的值的方法:
public void setXx(参数类型 参数){
this.xx = 参数;
}
二、继承
2.1 继承的概念
在原有类的基础上,产生一个新的类,在新的类中可以访问原有类中的非私有成员,并且可以添加一些自己独有的成员,这个过程叫做继承
2.2 类的继承的使用
使用extends关键实现两个类的继承关系
原有类:父类,根类,超类,基类
新的类:子类
2.3 语法
public class FatherClass{
//属性
//方法
}
public class ChildClass extends FatherClass{
//属性
//方法
}
2.4 不能被子类继承的成员
1)私有成员:私有成员不能被子类继承
2)构造方法:父类中的构造方法不能被子类继承,但是会在子类的构造方法中调用(子类的构造方法中默认第一条语句是调用父类的构造方法)
3) 静态成员(Static修饰的)不能被继承
2.5 继承的特点
1)类单继承,一个子类只能有一个父类;但是,一个父类可以有多个子类
2)子类只能继承父类中非私有的成员
3)父类的引用可以指向子类的实例,但是,父类的引用无法访问子类中独有的成员
2.6 继承中的构造方法
父类中的构造方法不会被子类继承,但是创建子类对象时,会调用父类的构造方法。也就是说,创建子类对象时,需要先创建一个父类的对象,在父类对象实例的内存的基础上附加一块子类独有成员的内存整体是一个子类对象。
2.7 继承代码实现
继承一
//父类(超类)
public class SuperClass {
public String name = "父类-张三"; //可见度:任何类中都可调用
int age; //可见度:同包下可见(调用)
protected String job; //保护型的修饰符在同包下可以访问,不同包下有继承关系也可以访问
private String salary; //私有修饰符,只有自己能访问
SuperClass() {
System.out.println("父类构造器");
}
void eat() {
System.out.println("父类-我吃中餐");
}
public void sleep() {
System.out.println("父类-我准备休息");
}
}
public class SubClass extends SuperClass {
public String name;//null
public SubClass() {
System.out.println("子类构造器");
}
@Override
public void sleep() { //子类重写父类方法
System.out.println("子类准备睡觉");
}
public void study() { //子类独有的方法
System.out.println("子类要学习");
}
public static void main(String[] args) {
// SuperClass super1 = new SuperClass();
// super1.sleep(); //父类对象掉父类的
//new子类会先调用父类构造器
// SubClass sub1 = new SubClass(); //创建子类对象 父类构造器 子类构造器
// sub1.sleep(); //子类准备睡觉
// sub1.study(); //子类要学习
//父类的引用指向子类实例(new子类赋给父类)
//1.父类没有子类中这个方法,就调用不了
//2.子类重写了父类方法,就调用子类的方法
//非静态方法的重写是java多态的一种表现,将子类赋给父类时,调用重写的非静态方法会调用子类,其他都调用父类
// SuperClass sub2 = new SubClass(); //父类构造器 子类构造器
// sub2.eat();//没有重写,调用到父类的 父类-我吃中餐
// sub2.sleep();//重写了此方法,调用子类 子类准备睡觉
//sub2.study(); //这样会编译不通过,study方法为子类独有,父类中没有此方法,所有父类引用不能访问
//父类实例可以强制转给子类引用,编译能通过,但是运行会报错
//java.lang.ClassCastException 类型转换错误
SubClass sub3 = (SubClass) new SuperClass();
}
}
继承二:代码实现对下面这句话的理解
非静态方法的重写是java多态的一种表现,将子类赋给父类时,调用重写的非静态方法会调用子类,其他都调用父类
//父类(超类)
public class SuperClass {
public String name = "父类-张三"; //可见度:任何类中都可调用
int age=10; //可见度:同包下可见(调用)
protected String job="Super job"; //保护型的修饰符在同包下可以访问,不同包下有继承关系也可以访问
private String salary="super salary"; //私有修饰符,只有自己能访问
SuperClass() {
System.out.println("父类构造器");
}
void eat() {
System.out.println("父类-我吃中餐");
}
public static void method() {
System.out.println("super static method");
}
public void sleep() {
System.out.println("父类-我准备休息");
}
}
public class SubClass extends SuperClass {
//属性跟父类完全相同
public String name = "子类-李四"; //可见度:任何类中都可调用
int age=5; //可见度:同包下可见(调用)
protected String job="Sub job"; //保护型的修饰符在同包下可以访问,不同包下有继承关系也可以访问
private String salary="Sub salary"; //私有修饰符,只有自己能访问
public SubClass() {
System.out.println("子类构造器");
}
@Override
public void sleep() { //子类重写父类方法
System.out.println("子类准备睡觉");
}
@Override
void eat() {
System.out.println("子类-我吃西餐");
}
public static void method() {
System.out.println("sub static method");
}
public static void main(String[] args) {
//父类引用指向子类
//非静态方法的重写是java多态的一种表现,将子类赋给父类时,调用重写的非静态方法会调用子类,其他都调用父类
SuperClass sub1 = new SubClass(); //父类构造器 子类构造器
System.out.println(sub1.age); //10
System.out.println(sub1.job); //Super job
System.out.println(sub1.name); //父类-张三
sub1.method(); //super static method
sub1.sleep(); //子类准备睡觉
//System.out.println(sub1.salary);//salary是private修饰,所以编译报错
}
}
继承三:三个类,SuperClass\SubClass\ThreeClass
SubClass继承SuperClass,ThreeClass继承SubClass,ThreeClass类可以访问SuperClass类的,但是如果SubClass把重写父类的属性变为私有,ThreeClass则再无法访问,Subclass进行了屏蔽。
ThreeClass可以访问到SuperClass的静态的salary:
public class ThreeClass extends SubClass{
public static void main(String[] args) {
SuperClass th = new ThreeClass();
System.out.println(th.name);
th.eat();
}
}
父类-张三
父类-我吃中餐
若将SubClass中的属性设为私有,则无法访问到SuperClass的属性。
继承的总结:
在继承关系中,
1.子类继承了父类的非私有成员变量或方法
2.子类中方法名如果和父类方法名一致,参数个数和类型不同,也是方法的重载 overload
3.子类中方法名如果和父类方法名一致,参数个数和类型相同,叫方法的重写 Override
4.继承关系中,new子类,会先new父类构造器,再new子类构造器
5.子类如果重写了父类的方法,作用域范围和父类相同或比父类大(优点要发扬光大),异常范围和父类相同或比父类小(缺点要尽量避免)
6.非静态方法的重写是java多态的一种表现,将子类赋给父类时,调用重写的非静态方法会调用子类,其他都调用父类
7.将子类实例赋给父类时,调用方法,如果父类中没有该方法就调用不到。
三、多态
3.1 什么是多态
一个事物有多种表现形态
对象的多种形态,方法的多样性。
3.2 对象向上转型,向下转型
向上转型:将子类的引用赋值给父类引用,自动转换
String str = “abc”;
Object obj = str;
SuperClass sub2 = new SubClass();
向下转型:将父类的引用赋值给子类引用,强制转换
SubClass sub3 = (SubClass) new SuperClass();
Object obj = new String(“abc”);
String str = (String)obj;
3.3 instanceof关键字
对象向下转型时,存在一个问题:
若一个父类A的引用a,指向一个子类B的实例,将a赋值给另一个子类C引用时,会抛出java.lang.ClassCastException异常;
抛出异常后程序将不能继续向下执行,为了避免这个异常的抛出,我们可以通过instanceof关键字判断引用指向的实例是否可以进行强制转换成某个子类对象
用法:
result = object instanceof class
参数:
result :布尔类型。
object :必选项。任意对象表达式。
class:必选项。任意已定义的对象类。
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
已知Animal类有两个子类Dog和Cat:
public class Demo{
public static void main(String[]args){
Animal a = new Dog();
check(a);
}
//设计一个方法,判断一个动物是猫还是狗
public static void check(Animal a){
if(a instanceof Dog){
System.out.println("狗");
}else if(a instanceof Cat){
System.out.println("猫");
}
}
}
3.4 多态的体现
对象的多态:
父类引用指向子类实例
接口引用指向实现类实例
方法的多样性:方法名相同,执行不同
方法的重写:子类中对父类继承来的方法进行完善,方法名,返回值类型,参数列表必须相同,访问权限高于或等于父类级别,子类重写的方法产生的异常要低于或等于父类的。
方法的重载:方法名相同参数列表不同,返回类型改变不产生影响。