java之三大特性
封装、继承、多态
文章目录
一、三大特性有哪些?
java的三大特性,包括:封装、继承、多态。
二、封装
2.1 概念
尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。
2.2 为什么学封装?
当我们在调用对象的属性时,往往通过对象名.属性名
这种形式来获取数据或修改数据。以下面的user类的数据调用来说明:
class User{
String name;//姓名
double money;//余额
int age;//年龄
public void show(){//打印信息
System.out.printf("姓名:%s\n余额:%f\n年龄:%d",this.name,this.money,this.age);
}
}
public class Test{
public static void main(String[] args){
User user = new User();//创建对象
//为属性赋值
user.name = "张三";
user.money = 100;
user.age = 16;
user.show();
}
}
输出结果:
姓名:张三
余额:100.000000
年龄:16
这很正常,对吧?
但是在生活中,属性的赋值不是在代码中写,而是通过输入来控制,即:
Scanner input = new Scanner(System.in);
System.out.println("请输入姓名:");
user.name = input.next();
System.out.println("请输入余额:");
user.money = input.nextDouble();
System.out.println("请输入年龄:");
user.age = input.nextInt();
user.show();//打印输入的信息
以上这种提示+输入
的流程才是程序设计中的常态
身为程序设计者的我们,自然希望属性是正确的,但:
请输入姓名:
awwrg
请输入余额:
-123523
请输入年龄
-999
输出结果:
姓名:awwrg
余额:-123523
年龄:-999
上面的数据,很明显,是不符合现实情况的
客观上:
- 就目前的技术而言,并没有办法对属性的赋值加以控制
- 毫无意义的数据存入我们的程序中,对于数据库来说就是垃圾
主观上:
- 我们不能赌数据输入者的智商和道德
- 我们希望程序能按照我们想要的效果运行
所以我们需要对属性加以限制,需要对属性进行封装(private):
private int age;
private是一个访问修饰符,它可以让类中被其修饰的数据无法直接获取和修改。
那我们怎么去调用属性呢?
private虽然禁止了类外调用属性,但在类中是不加限制的
所以我们可以编写专门的方法去获取和设置数据:
public 数据类型 get()
:专门用于获取类中被封装的数据。
public int getAge(){//被获取的数据开头大写
return this.age;//返回需要获取的数据
}
public void\boolean set(数据类型 形参)
:专门用于设置类中被封装的数据
public boolean setAge(int age){//对
if(age <= 0 || age >120)//对数据进行逻辑判断,结合现实情况
return false;
this.age = age;//符合要求的数据才会被获取
return true;
}
2.3 代码演示
2.3.1 类中设置
class User{
//封装的属性只能在类中使用
private String name = "张三";//封装姓名,设置默认值
private double money;//封装余额
private int age = 18;//封装年龄,设置默认值
public String getName(){//专门用于获取姓名的方法
return this.name;//直接返回
}
public boolean setName(String name){//专门用于设置姓名的方法
//本人太菜,暂时还不会如何判断姓名是否正确···
//经过一系列逻辑判断后···
this.name = name;//确实是姓名,获取
return true;
}
public double getMoney(){//专门用于获取余额的方法
return this.money;
}
public boolean setMoney(double money){//专门用于设置余额的方法
if(money < 0)//钱不可能是负数
return false;
this.money = money;
return true;
}
public int getAge(){//专门用于获取年龄的方法
return this.age;
}
public boolean setAge(int age){//专门用于设置年龄的方法
if(age <= 0 || age > 120)//年龄不可能是负数,世界上最长寿的人也就120吧。。
return false;
this.age = age;
return true;
}
}
原则上来讲,类中的任何属性都需要封装
2.3.2 主类调用
import java.util.Scanner;
public class Test{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
User user = new User();//创建对象
System.out.println("请输入姓名:");
String name = input.next();
if(!user.setName(name))//判断数据是否正确
System.out.println("姓名错误!");
System.out.println("请输入年龄:");
int age = input.nextInt();
if(!user.setAge(age))
System.out.println("年龄错误!");
System.out.println("请输入余额:");
double money = input.nextDouble();
if(!user.setMoney(money))
System.out.println("余额错误!");
System.out.println("姓名:" + user.getName());//通过get方法获取数据
System.out.println("年龄:" + user.getAge());
System.out.println("余额:" + user.getMoney());
}
}
输出结果:
请输入姓名:
张三
请输入年龄:
-9
年龄错误!
请输入余额:
1515
姓名:张三
年龄:18
余额:1515.000000
2.4 注意事项
- private不能作为类的访问修饰符
- private修饰的属性或方法,只能在类中直接调用
- 添加privave时,一定要添加
get()
和set()
方法,不然没有任何意义
三、继承
3.1 概念
继承:一个类继承另一个类可以被继承的成员。关键字为extends
3.2 方法重写
子类将从父类继承而来的方法进行改变。
规则:
- 子类重写父类方法时,须与父类方法的方法名一致、返回值类型一致、参数列表一致(
参数类型
、参数数量
、参数顺序
) - 子类重写父类的方法,在子类中被优先调用,可使用
super.方法名
调用父类方法。
class Animal{
public void show(){//父类的方法
System.out.println("动物正在吃东西···");
}
}
class Cat{
public void show(){//子类重写父类的方法
System.out.println("猫正在吃东西···");
}
}
3.3 代码演示
父类–Animal:
class Animal{//动物类
private String nickname;
private int age;
private String furcolor;
public void eat(){
System.out.println("动物在吃东西···");
}
public void sleep(){
System.out.println("动物在睡觉···");
}
public String getNickname(){
return this.nickname;
}
public void setNickname(String name){
this.nickname = nickname;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
public String getFurcolor(){
return this.furcolor;
}
public void setFurcolor(String furcolor){
this.furcolor = furcolor;
}
}
子类–Cat:
class Cat extends Animal{//猫类,继承了动物类
public void eat(){//重写父类的eat方法
System.out.println(getNickname() + "猫在吃东西···");//调用父类方法
}
public void sleep(){//重写父类的sleep方法
System.out.println(getNickname() + "猫在睡觉···");//调用父类方法
}
public void show(){//显示动物信息
System.out.println("昵称:" + getNickname());
System.out.println("年龄:" + getAge());
System.out.println("毛色:" + getFurcolor());
}
}
主类:
import java.util.Scanner;
public class Test{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
Cat cat = new Cat();//创建子类对象
System.out.println("请输入昵称:");
cat.setNickname(input.next());//调用父类方法
System.out.println("请输入年龄:");
cat.setAge(input.nextInt());//调用父类方法
System.out.println("请输入毛色:");
cat.setFurcolor(input.next());//调用父类方法
cat.show();
cat.eat();
cat.sleep();
}
}
输出结果:
请输入昵称:
小黑
请输入年龄:
3
请输入毛色:
黑色
昵称:小黑
年龄:3
毛色:黑色
小黑猫在吃东西···
小黑猫在睡觉···
3.4 特点
- 子类可直接调用父类的非private属性和方法。
- 重写父类方法时,修饰符可以与父类方法相同,或更宽广,不能更窄!!
四、多态
4.1 概念
多态有两种表现形式:向上转型
和向下转型
。
4.1.1 向上转型
使用父类引用,获取子类的对象:
父类类名 对象名 = new 子类类名();
Animal cat1 = new Cat();
4.1.2 向下转型
仅限向上转型后:
使用子类引用,将经过向上转型的对象强转为子类类型
子类类名 对象名 = (子类类型) 向上转型过的对象;
Cat cat2 = (Cat)cat1;
例:
父类–Animal:
public class Animal{
public void eat(){
System.out.println("动物在吃东西");
}
}
子类–Cat:
public class Cat extends Animal{//继承了Animal类
public void eat(){//子类重写父类的方法
System.out.println("猫咋吃东西");
}
public void play(){//子类独有的方法
System.out.println("猫在玩毛线");
}
}
主类创建对象:
public clas Test{
public static void main(String[] args){
Animal cat = new Cat();//向上转型
cat.eat();//此时cat只能调用父类的成员及子类重写父类的方法
Cat cat2 = (Cat)cat;//向下转型
cat2.play();//cat2是纯正的Cat类型,可以调用其独有的方法
}
}
输出结果:
猫在吃东西
猫在玩毛线
4.2向上转型的应用
4.2.1 作为方法参数
向上转型可应用在方法中,作为方法的参数
父类中:
public class Animal{
String nickname;
int age;
String furcolor;
public void show(Animal an){//通过向上转型的方式,获取子类对象,不必单独指定子类类型
System.out.println("姓名:" + an.nickname);
System.out.println("年龄:" + an.age);
System.out.println("毛色:" + an.furcolor);
}
}
子类Cat和Dog:
class Cat extends Animal{
Cat(){//无参构造方法
}
Cat(String nickname,int age,String furcolor){
super.nickname = nickname;
super.age = age;
super.furcolor = furcolor;
}
}
class Dog extends Animal{
Dog(){//无参构造方法
}
Dog(String nickname,int age,String furcolor){
super.nickname = nickname;
super.age = age;
super.furcolor = furcolor;
}
}
主类中
public class Test{
public static void main(String[] args){
Animal an = new Animal[3];
Cat cat = new Cat("小黑",3,"黑色");
Dog dog = new Dog("旺财",2,"棕色");
an.show(cat);//子类对象通过向上转型的方式接收
an.show(dog);
}
}
输出结果:
姓名:小黑
年龄:3
毛色:黑色
姓名:旺财
年龄:2
毛色:棕色
4.2.2 作为数组元素
子类对象可作为父类对象数组中的元素
public class Test{
public static void main(String[] args){
Animal[] an = new Animal[2];//父类对象数组
Cat cat = new Cat("小黑",3,"黑色");
Dog dog = new Dog("旺财",2,"棕色");
an[0] = cat;//子类对象可通过向上转型的方式作为父类对象数组中的元素
an[1] = dog;
}
}
4.3 特点
- 向上转型的对象,可以调用父类的属性和方法,以及子类重写的方法
- 向上转型的对象,不能调用子类独有的属性和方法!!
- 向下转型的对象,只是子类的对象,可以调用子类独有的属性及方法。
总结
这是我写的第二篇博客,新人一个,如有错误或建议请多在评论区批评指正,谢谢!