一、封装或隐藏 (Encapsulation)
使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题。
public class Animal {
public int legs;
public void eat(){
System.out.println(“Eating.”);
}
public void move(){
System.out.println(“Moving.”);
}
}
public class Zoo{
public static void main(String args[]){
Animal xb=new Animal();
xb.legs=4;
System.out.println(xb.legs);
xb.eat();xb.move();
} }
应该将legs属性保护起来,防止乱用。
保护的方式:信息隐藏
信息的封装和隐藏
Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的:
1、隐藏一个类中不需要对外提供的实现细节; 2、使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
3、便于修改,增强代码的可维护性;
权限修饰符
对于class的权限修饰只可以用public和default。 public类可以在任意地方被访问。
default类只可以被同一个包内部的类访问。
二、继承 (Inheritance)
作用: 1、继承的出现提高了代码的复用性。 2、继承的出现让类与类之间产生了关系,提供了多态的前提。 3、不要仅为了获取其他类中某个功能而去继承
子类继承了父类,就继承了父类的方法和属性。
在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。
关于继承的规则: 子类不能直接访问父类中私有的(private)的成员变量和方法。
方法的重写
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
要求: 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。 重写方法不能使用比被重写方法更严格的访问权限。 重写和被重写的方法须同时为static的,或同时为非static的 子类方法抛出的异常不能大于父类被重写方法的异常
方法的重载(overload)
概念: 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
练习:
1.创建父类Person
package lesson03;
import java.io.IOException;
public class Person {
private int age;
String name;
protected double weight;
public boolean ismale;
public Person(){
}
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;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public boolean isIsmale() {
return ismale;
}
public void setIsmale(boolean ismale) {
this.ismale = ismale;
}
//在本类中调用上述属性
public void info(){
System.out.println(this.age);
}
public void info(String name){
System.out.println(this.name);
}//方法的重载,参数列表不同
public String show () throws IOException{
return null;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + ", weight=" + weight
+ ", ismale=" + ismale + "]";
}
}
2.创建子类Student
package lesson03;
import java.io.IOException;
/*
* Student类通过继承Person类,拿到Person“所有”的属性和方法
* Student类确实拿到了Person类中声明为private的属性,只是Student类的对象不能直接调用罢了
*
* 方法的重写:
* 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。
重写方法不能使用比被重写方法更严格的访问权限。
重写和被重写的方法须同时为static的,或同时为非static的
子类方法抛出的异常不能大于父类被重写方法的异常
问题:如果父类中有一个声明为private的方法,那么子类中是否可以重写该方法(NO)
*java语言是单继承的 ,支持类实现多个接口*/
public class Student extends Person {
public Student(){
super();
}
public String show () throws IOException{
return super.toString();//执行父类的toString
}
public String toString() {
return "Student [age=" + this.getAge() + ", name=" + name + ", weight=" + weight
+ ", ismale=" + ismale + "]";//Age的属性时private,所以不能直接调用,只能用get
}
public static void main(String[] args){
Student s = new Student();
s.setAge(12);
s.ismale = true;
s.name = "Peter";
System.out.println(s.toString());
}
}
三、 多态 (Polymorphism)
多态性,是面向对象中最重要的概念,在java中有两种体现:
1、方法的重载(overload)和重写(overwrite)
2、对象的多态性 ——可以直接应用在抽象类和接口上
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
虚拟方法调用(多态情况下)
Person e = new Student();
e.getInfo(); //调用Student类的getInfo()方法
编译时类型和运行时类型
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
多态前提: 需要存在继承或者实现关系 要有覆盖操作
成员方法: 编译时:要查看引用变量所属的类中是否有所调用的方法。 运行时:调用实际对象所属的类中的重写方法。
成员变量: 不具备多态性,只看引用变量所属的类。
练习:
1.创建父类Person1
package lesson03;
public class Person1 {
private String name;
int age;
public void walk(){
System.out.println("人走路");
}
public void eat(){
System.out.println("人吃饭");
}
}
2.创建子类Man1
package lesson03;
public class Man1 extends Person1{
boolean isSmoking;
public void walk(){
System.out.println("男人笔挺地走路");
}
public void eat(){
System.out.println("男人大口吃肉");
}
public void smoking(){
System.out.println("男人抽烟");
}
}
3.创建子类Woman1
package lesson03;
public class Woman1 extends Person1 {
public void walk(){
System.out.println("女人淑女地走路");
}
public void eat(){
System.out.println("女人小口地吃饭");
}
}
4.创建Test类
package lesson03;
/*多态的前提
* 1.要有类的继承
* 2.子类要有方法重写*/
public class TestPerson {
public static void main(String[] args){
Person1 p1 = new Person1();
// p1.walk();
// p1.eat();
func(p1);
Man1 m = new Man1();
// m.walk();
// m.eat();
func(m);
Woman1 w = new Woman1();
// w.walk();
// w.eat();
func(w);
System.out.println("##########");
//对象的多态:创建子类对象,并将此对象赋给父类的引用
Person1 p2 = new Man1();
// p2.walk();
// p2 = new Woman1();
//虚拟方法调用!编译时状态和运行时状态
p2.walk();
//p2.smoking();//不能使用子类特有的方法
}
public static void func(Person1 p){
p.walk();
p.eat();
if(p instanceof Man1){//判断对象p是否是Man1 的一个实例,如果是的话,进行强转,这个时候可以使用Man1特有的方法smoking
Man1 m = (Man1) p;
m.smoking();
}
}
}
运行结果:
人走路
人吃饭
男人笔挺地走路
男人大口吃肉
男人抽烟
女人淑女地走路
女人小口地吃饭
##########
男人笔挺地走路
instanceof 操作符
x instanceof A:检验x是否为类A的对象,返回值为boolean型。 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。 如果x属于类A的子类B,x instanceof A值也为true。