一、封装
封装:包装、隐藏内部细节,对外提供接口。
可以认为封装是一层保护,防止类中代码和数据被外部随意访问,提供有接口,规范化使用该类数据,增强了安全性。
1.实现封装
1.1属性
属性一般用private修饰(除需要被继承)来限制对属性的访问。
public class Test {
private int age;
private String name;
}
private修饰了age,name,使其成为私有属性,只有本类可以访问,其他类不能访问。
1.2创建需要的赋取值方法
public class Test {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建get、set方法来提供接口操作该类数据。(this引用调用方法的对象来解决属性和参数名相同的问题)
1.3访问封装类
上面实现了大概的封装类。
public static void main(String[] args) {
Test test=new Test();
test.setAge(20);
test.setName("xiaoming");
System.out.println(test.getAge());
System.out.println(test.getName());
}
创建Test类对象test,用对象调用方法操作数据
输出:
二、继承
继承是面向对象程序设计的重要手段,可以在保留原有类的特性上继续扩展,增加新的功能,产生新的类(派生类)。
继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
2.1为什么需要继承
一个大类的动物,不同的数码产品等等,它们都会有相同的属性和行为。
比如猫和狗,它们都有名字(name),年龄(age),都会有吃饭(eat())、睡觉(sleep()的行为。
而我们分别去定义一个猫类和狗类就会有很多重复的代码,这时候就需要使用继承。
2.2继承语法d
Dog继承Animal类 (extends)
public class Dog extends Animal{
}
1.子类(派生类)将会继承父类(基类)的成员变量(属性)和成员方法(行为)。
2.子类继承父类后必须有添加自己特有成员,不然不用继承。
例(三个.java)
public class Animal {
public String name;
public int age;
public void eat(){
System.out.println("Animal...eat");
}
public void sleep(){
System.out.println("Animal...sleep");
}
}
public class Cat extends Animal{
public void leap(){
System.out.println("Cat...leap");
}
}
public class Dog extends Animal{
public void tuS(){
System.out.println("Dog....tuS");
}
}
2.3访问父类成员
2.3.1访问父类成员变量
1.无相同变量名
子类可以直接使用。(非private修饰)
2.有相同变量名
class A{
public int x=20;
}
public class Test extends A{
public int x=30;
public void printX(){
x=40;
super.x=40;
}
}
x=40;访问自己(就近)的默认this. 。super.x=40;访问父类的
2.3.1子类访问父类成员方法
1.成员方法名字不同。
与访问成员变量一样。
2.成员方法名字相同
(1)参数列表不同
根据调用规则传参调用。
(2)重写(override)
子类对象无法调用,子类方法用super.
2.4super关键字
super:解决子类方法访问父类成员
*.子类非静态方法中使用
class A{
public int x=20;
public void methodB(){
System.out.println("methodB ...A");
}
}
public class Test extends A{
public int x=30;
public void printX(){
x=40;//默认this.访问子类的x
super.x=40;//访问父类x
}
@Override
public void methodB() {
System.out.println("methodB....Teat");
}
public void useM(){
methodB();//子类的方法
super.methodB();//父类方法
}
}
2.5子类构造方法
现有父才有子,子类构造需要调用父类构造方法。先调用父类构造再调用子类构造。
public class A {
public int age;
public A(int age) {
this.age = age;
}
}
public class B extends A{
public int y;
public B(int age, int y) {
super(age);
this.y = y;
}
}
*
1.父类是无参或者默认构造方法时,子类构造方法第一行默认有super()。
2.父类构造方法有参,子类必须实现有参构造,必须第一行用super(参数...)初始化继承成员变量。
3.子类构造方法中super()只能出现一次,并且不能和this()同时出现(this()也必须在第一行)。
2.6 this和super
相同点:
1.java关键字
2.只能在类的非静态成员方法中使用,用来访问非静态成员。
3.在构造方法中可以调用(只能在第一条语句,且不能同时存在)
不同点:
1.this是当前对象引用,super是继承的部分成员引用。
2.this(...)调用子类构造方法,super(调用父类构造方法)
3.子类super()调用一定存在,没有时,编译器会自动增加。this()不写则没。
2.7初始化执行顺序
顺序:
public class Person {
public String name;
public int age;
static {
System.out.println("父类静态代码块。。");
}
{
System.out.println("父类实例代码块。。");
}
public Person() {
System.out.println("父类构造代码块。。");
}
}
public class Student extends Person{
public String ID;
static {
System.out.println("子类静态代码块。。");
}
{
System.out.println("子类实例代码块。。");
}
public Student() {
System.out.println("子类构造代码块。。");
}
}
public class Test {
public static void main(String[] args) {
Student student=new Student();
}
}
2.8访问限定符
限制成员访问权限
*父类private修饰的成员也会继承到子类,但是不能直接访问,可以用父类的方法访问。
*成员应该加以比较严格的访问权限,增加数据的安全性。
2.9继承的方式
*1.继承层数不是越多越好,继承层数越多结构越复杂,可能需考虑重构。
2.一般不超过三层。
3.不想被继承的类用final修饰。
2.10 final
1.修饰成员变量,表示常量(不能被修改)。需要就地初始化
class A {
public final int a=20;
}
2.修饰类,类成为密封类(不能被继承)。
public final class A {
public final int a=20;
}
class B extends A{
//...
}//error
3.修饰方法,方法就不能被重写。
2.11继承和组合
继承表示is-a关系:如Dog是animal。
组合表示has-a关系:如电脑有cpu。
*1.继承是继承父类成员,组合是类作为成员。
2.都能实现代码复用,尽量使用组合。
三、多态
多态:不同的对象完成某一个行为,会产生不同的状态。
3.1实现条件
java中:
1.在继承体系
2.子类重写父类方法
3.通过父类引用调用重写方法
3.2重写
重写(override):子类对父类方法进行重新编写,完成自己需要的行为,返回值和参数列表不变。
重写规则:
1.子类重写方法与父类方法原型一致,返回值、参数列表相同。(返回值可以具有父子关系)
2.访问权限必须比父类方法大
3.父类被final、static、private修饰的无法重写
4.用@override注解重写方法(多一条校验)
3.2.1重写与重载的区别
重写是运行时的多态,重载是编译时的多态。
class B{
public void print(){
System.out.println("B...print");
}
}
public class A extends B{
@Override//重写父类B的print方法
public void print() {
System.out.println("A...print");
}
//重载add方法
public int add(int x,int y){
return x+y;
}
public double add(double x,double y){
return x+y;
}
}
3.3向上转型和向下转型
3.3.1向上转型:用父类对象接收子类对象
三种形式:(B为A父类)
1.直接赋值
eg.
B b=new A();//B为A的父类
2.方法传参
public class Test {
public static void fun(B b){
}
public static void main(String[] args) {
A a=new A();
fun(a);
}
}
3.方法返回
public static B fun(A a){
return a;
}
*向上转型:
1.让代码更加简单灵活
2.无法调用子类特有方法
3.调用子类重写方法时会执行子类重写的方法
3.3.2向下转型:一般用于子类向上转型后想调用子类方法,就进行向下转型。
缺陷:向下转型可以转错类型。
instanceof 关键字
public class Test {
public static B fun(A a){
return a;
}
public static void main(String[] args) {
A a=new A();
B b=a;
if(b instanceof A){
System.out.println("b 是由a向上转型的 ");
}
}
}
3.4多态优缺点
优点:
1.降低圈复杂度,避免大量使用if -else
2.可扩展能力强
缺点:
1.运行效率低
2.成员变量、构造方法没有多态