使用private修饰符对属性进行修饰,限制属性的访问权限,只有类内部能够访问这样的属性,其他的类通过对象、属性的方式是无法访问的,从而对对象的状态(数据)进行保护,外部类要访问的话需要通过调用get/set的方法,保证属性统一访问
-
学生类student
有一些属性,都是用private修饰
提供get、set方法访问属性,在set时候可以限制赋值的内容,在get时可以返回指定格式的数据,转换和限制逻辑封装在类中
public class Student {
//private 私有修饰符
private String name;
private int sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
//返回字符串
String result = sex == 1? "男" : "女";
return result;
}
public void setSex(int sex) {
//限制性别的赋值,不允许随便赋值
if(sex < 0 || sex > 1){
throw new RuntimeException("性别只能为0或1");
}
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
-
使用学生类StudentTest
使用学生类时不能直接访问属性,必须通过get、set方法
如果给属性(成员变量)赋值不符合要求就报异常
用get方法读取属性,会读取到学生类转换之后的内容
public class StudentTest {
public static void main(String[] args) {
Student student = new Student();
// student.name = "小丽";//私有成员变量,不能直接用对象.属性访问
student.setAge(22);
student.setSex(1);//对性别赋值,赋值的时候set对其限定输入
System.out.println(student.getSex());//打印赋的性别,返回的时候get指定返回格式
}
}
访问修饰符
控制访问权限的关键字称为访问修饰符,有private、default、protacted、public(类前面只能用public)
访问修饰符可以用在成员变量以及方法前面。局部变量不需要访问修饰符
| 同类 | 同一个包 | 子类 | 其他类 | |
|---|---|---|---|---|
| private | √ | × | × | × |
| default(不写修饰符) | √ | √ | × | × |
| protected | √ | √ | √ | × |
| public | √ | √ | √ | √ |
注(自己理解):
private:相当于自己,我的私人物品我自己(同类:我自己)能用,其他人(同一个包、子类、其他类:不是我的)所有都不能用
default:相当于恋爱的情侣,两人共有(同类、同一个包:吃的、穿的)的一些东西能用,外人(子类、其他类:)不能对我们的恋情指手画脚
protected:相当于一家人,家(同类、同一个包、子类)里面的物品可以直接用,家(其他类)以外的不能用
public:公共的,没有限制,想用就用(同类、同一个包、子类、其他类)
继承A类可以通过extends关键字继承B类,继承之后A类可以有一些B类中的属性或方法,实现代码重复利用
语法:
【修饰符】class 子类 extends 父类{
}
子类也叫派生类,或者叫衍生类,subClass
父类也叫基类,超类,superClass
继承的特点-
继承只能单继承,只能有一个父类;一个父类可以有多个子类
-
继承可以多重继承:A继承B,B继承C
-
Object是所有类的父类(所有的类都是继承至Object)
-
子类可以重写(覆盖)父类的方法
-
在创建子类的时候,会先去执行父类的构造方法
父类 Shap定义了一个成员变量name,一个方法area()
子类Retangle继承了父类Shap,Retangle自动有name属性和area()方法
子类中定义自己的属性,也可以写自己的方法,还可以重写父类继承来的方法
-
父类Shap
public class Shap {
public String name;
public void area(){
System.out.println("显示图形的面积");
}
}
-
子类Retangle
//extends 关键字
public class Retangle extends Shap{
private float width;//定义私有属性 矩形的宽度
private float height;//矩形的高 类的属性通过构造方法赋值
public Retangle(float width, float height) {
this();//调用无参的构造方法; 在构造方法中调用其他构造方法代码写在第一行
this.width = width;
this.height = height;
}
public Retangle() {
this.name = "矩形"; //对name赋值
}
@Override //注解:这是重写或者覆盖父类的方法
public void area() { //面积
float area = width * height;
System.out.println(area); //输出面积area
}
}
-
测试代码
public class RetandleTest {
public static void main(String[] args) {
Retangle retangle = new Retangle(5,4);//对高和宽赋值
retangle.area();//使用Retangle的area方法
System.out.println(retangle.name);//输出name
}
}
重写和重载
重写override(覆盖)
当子类继承父类的时候,对父类的方法代码重写写过,就叫重写
重写的特性:
-
方法名、参数列表(个数、类型、顺序),返回类型完全一致
-
访问权限(修饰符)不能比父类更小(跟父类的访问权限一样或更大)
-
如果要抛出异常,不能够比父类的异常更大
在一个类中(不一定要继承),如果有多个方法名相同,参数列表不同(个数、类型、顺序),这些同名的方法称为重载
重载的特性:
-
方法名相同
-
参数列表不同(个数、类型、顺序)
public class Rect {
//计算正方形面积
public void area(int width){
System.out.println(width * width);
}
//方法名相同,参数不同
//计算长方形面积
public void area(int width , int height){
System.out.println(width * height);
}
}
this和super关键字
这两个关键字都可以指代对象或构造方法
当成对象用的
public Shap() {
this.name = "形状"; //在构造方法里this代表当前对象
System.out.println(this.name);
}
public void setAge(int age) {
this.age = age; //age是局部变量,加this.age的是成员变量
}//this用在set方法里面,代表当前对象
public void parentArea(){
super.area();//在子类中要去访问父类的方法,用super.方法()
}
当成构造
方法使用
-
在构造方法中调用构造方法,用this代替构造方法名。
-
在构造方法中调用构造方法,调用语句只能放在第一行
-
子类要调用父类的构造方法,用super()
-
如果子类的构造方法没有调用父类的构造方法,默认会调用父类的无参的构造方法
-
如果父类没有无参的构造方法,在子类的构造方法中必须要去(super)调用父类的有参的构造方法
public class Parent {
private int age;
private String name;
private int sex;
public Parent() {
System.out.println("无参");
}
public Parent(String name, int sex) {
this.name = name;
this.sex = sex;
System.out.println("两个参数");
}
public Parent(int age, String name, int sex) {
this(name,sex);//调用两个参数的构造方法,用在第一行
this.age = age;
System.out.println("三个参数");
}
public static void main(String[] args) {
new Parent(22,"张三",1);
}
}
public class Son extends Parent{
private int age;
private String name;
private int sex;
public Son(){
super();//执行父类的构造方法,不写也会自动调用
System.out.println("son 无参");
}
public Son(String name, int sex) {
this.name = name;
this.sex = sex;
System.out.println("son 两个参数");
}
public Son(int age, String name, int sex) {
super(age,name,sex);
this.age = age;
this.name = name;
this.sex = sex;
System.out.println("son 三个参数");
}
public static void main(String[] args) {
// Son son = new Son();
new Son(22,"小王",0);
}
}
多态
一个类在编译的时候和运行时同一个方法呈现出不同的状态。
比如:动物类有一个发出叫声的方法,它的子类有猫类,猫的叫声是“喵喵”;还有一个子类是狗类,狗的叫声“汪汪”。 现在有一个动物类的对象,调用发出叫声的方法,有可能叫:喵喵,也可能叫:汪汪
形成多态的条件:
-
有继承关系,有多个子类,子类重写父类的方法
-
父类类型定义的变量,用子类的实例给它赋值
多态的用处:
统一管理,无限适配或扩展
-
Animal.java
public class Animal {
public void shout(){
System.out.println("动物在叫");
}
}
-
Cat
public class Cat extends Animal{
@Override
public void shout() {
System.out.println("喵喵喵");
// super.shout();
}
}
-
Dog
public class Dog extends Animal{
@Override //重写
public void shout() {
System.out.println("汪汪");
}
}
-
测试代码
public class AnimalTest {
public static void main(String[] args) {
Animal animal1 = new Animal();
animal1.shout();//动物类的叫声
Cat cat = new Cat();
cat.shout();//喵叫
Dog dog = new Dog();
dog.shout();
Animal animalCat = cat;//“喵喵喵” 赋值给 “动物在叫”
animalCat.shout();//喵叫“喵喵喵”
Animal animalDog = dog;
animalDog.shout();
}
}
向上造型
父类 变量 = new 子类();
父类定义的变量,用子类的实例对象赋值
注意:向上造型的时候,不能调用到子类中自己添加的方法
Animal animalCat = cat;//“喵喵喵” 赋值给 “动物在叫”
animalCat.shout();//喵叫“喵喵喵”
Animal animalDog = dog;
animalDog.shout();
向下造型
子类 变量 = (子类)父类的对象;
用父类的对象给子类的变量赋值,向下造型必须用强制类型转换
向下造型分几种情况:
-
直接new一个父类对象赋给子类变量,运行会报异常
-
父类对象是通过子类的对象向上造型上去的实例,这种对象可以向下造型,要强转,子类的所有方法都可以访问
-
跟2一样的做法,但是换了子类,如猫的子类的对象,向下造型成狗,不允许,运行时报异常
//向下造型
//1.直接用父类创建的对象赋给子类变量,会报异常
// Cat cat = (Cat) new Animal();
//2.把通过向上造型得到的父类对象赋给子类对象,可以调用继承至父类的方法,也可以子类自己的方法
Animal animal1 = new Cat();
System.out.println("*******向下*******");
Cat cat1 = (Cat) animal1;
cat1.shout();
cat1.eat();
//3.造型是子类发生了变化
System.out.println("********");
Animal animal2 = new Dog();
Cat cat2 = (Cat) animal2;//会报异常
cat2.shout();
cat2.eat();



