就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。
封装步骤:
1.将属性进行私有化private [外部不能直接修改属性]
2.提供一个公共的set方法,用于对属性判断并赋值
public void setXxx(类型 参数名) {
属性 = 参数名;
}
3.提供一个公共的get方法,用于获取属性的值
public 数据类型 getXxx(){ //权限判断
return xx;
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("小狗");
p1.setAge(18);
p1.setSalary(22222);
}
}
class Person {
public String name;
private int age;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
} else {
System.out.println("名字不合法,请重新输入!");
this.name = "打钩";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("年龄不合法,请重新设置!");
this.age = 18;
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("小狗");
p1.setAge(18);
p1.setSalary(22222);
}
}
class Person {
public String name;
private int age;
private double salary;
//无参构造器
public Person() {
}
//带三个属性的构造器
public Person(String name, int age, double salary) { //通过构造器下面的限制方法会失效
this.name = name;
this.age = age;
this.salary = salary;
//通过在构造器里写set下面的方法就不会失效
setName(name);
setAge(age);
setSalary(salary);
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
} else {
System.out.println("名字不合法,请重新输入!");
this.name = "打钩";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("年龄不合法,请重新设置!");
this.age = 18;
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
问题:如果两个类的属性和方法有很多是相同的,该怎么办?
这就用到了继承,解决代码的复用性问题,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。
继承的基本语法:
class 子类 extends 父类 {
}
子类就会自动拥有父类定义的属性和方法。
public class pupil extends student {
public void ing() {
System.out.println("小学生正在考试小学内容");
}
}
public class graduated extends student{
public void ing() {
System.out.println("大学生正在考试大学内容");
}
}
public class student {
public String name;
public int age;
private double score;
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public void out() {
System.out.println(name + "\n" + age + "\n" + score);
}
}
public class test {
public static void main(String[] args) {
pupil p = new pupil();
p.name = "银角";
p.age = 6;
p.setScore(66);
p.out();
p.ing();
System.out.println("=================================");
graduated g = new graduated();
g.name = "金角";
g.age = 18;
g.setScore(88);
g.out();
g.ing();
}
}
1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问。
public class father {
public int n1 = 100;
protected int n2 = 200;
int n3 = 300;
private int n4 = 400;
public father() { //无参构造器
}
public int getN4() { //父类提供的公共方法
return n4;
}
public void test100() {
System.out.println("test100");
}
protected void test200() {
System.out.println("test200");
}
void test300() {
System.out.println("test300");
}
private void test400() {
System.out.println("test400");
}
public void calltest400() { //父类再使用一个公共方法调用test400(),
// 这样子类使用这个方法就可以调用test400()
test400();
}
}
public class son extends father{
public son(){
System.out.println("son()...");
}
public void sayok() {
//非私有的属性和方法可以在子类直接访问
//但是私有的属性和方法不能再子类直接访问
System.out.println(n1 + " " + n2 + " " + n3);
test100();;
test200();
test300();
//test400(); 会报错,要使用的话,通过父类提供的公共的方法去访问。
calltest400();
System.out.println("n4=" + getN4());
}
}
public class test {
public static void main(String[] args) {
son son = new son();
son.sayok();
}
}
2.子类必须调用父类的构造器,完成父类的初始化。
当创建子类对象时,不管使用子类的那个构造器,默认情况下总会去调用父类的无参构造器 ,如果父类没有提供无参构造器,则必须在子类的构造器中使用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
3.如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
4.super在使用时,需要放在构造器的第一行。super只能在构造器中使用。
5.super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器。
6.Java所有类都是Object类的子类
7.父类构造器的调用不限于直接父类,将一直往上追溯直到Object类。
8.子类最多只能继承一个父类(指直接继承),即Java中是单继承机制。
现有一个A类,A extends B ,B extends C ,A,B,C 中都含有一个相同的属性 name ,现在创建一个对象,A a = new A(); a.name; 其中 name 是A,B,C 哪个类的name,结果应该按照下面的步骤来:
1.首先看子类是否有该属性,如果子类有,并且可以访问,则返回信息。
2.如果子类没有这个属性,就看父类有没有,有并且可以访问,就返回信息。
3.如果父类也没有,就按照这样一直往上查询直到Object类。
super代表父类的引用,用于访问父类的属性,方法,构造器。
1.访问父类的属性,但不能访问父类的private属性
2.访问父类的方法,但不能访问父类的private方法
3.访问父类的构造器,只能放在构造器的第一句,只能出现一句。
super.cal(); //找cal方法的顺序是直接找父类,跳过本类。
super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。A->B->C
方法重写就是子类有一个方法,和父类的某个方法的名称,返回类型,参数一样,那么我们就说子类的这个方法覆盖了父类的方法。
子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类,比如:父类 返回类型是 Object ,子类方法返回类型是String,
public Object test(){} 和 public String test(){}
子类方法不能缩小父类方法的访问权限。
方法或对象具有多种形态,多态是建立在封装和继承的基础之上的。重写和重载就体现多态。
对象的多态:
1.一个对象的编译类型和运行类型可以不一致。
Animal animal = new Dog(); {编译类型是Animal,运行类型是Dog}
2.编译类型在定义对象时,就确定了,不能改变。
3.运行类型时可以变化的。
4.编译类型看定义时 = 号 的左边,运行类型看 = 号 的右边。
多态前提是:两个对象(类)存在继承关系。
多态的向上转型
本质:父类的引用指向了子类的对象
语法:父类类型 引用名 = new 子类类型();
特点:编译类型看左边,运行类型看右边
可以调用父类中的所有成员(需遵守访问权限)。
不能调用子类中特有成员。
最终运行效果看子类的具体实现。即调用方法时,按照从子类开始查找方法,然后调用,规则与前面讲的方法调用规则一致。
public class Animal {
String name = "动物";
int age = 18;
public void eat() {
System.out.println("吃");
}
public void sleep() {
System.out.println("睡");
}
public void run() {
System.out.println("跑");
}
public void show() {
System.out.println("hello 你好");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
public class test {
public static void main(String[] args) {
Animal animal = new Cat();
Object obj = new Cat();
// animal.catchMouse; 不能调用,因为在编译阶段,能调用那些成员,是由编译类型来决定的
}
}
语法:子类类型 引用名 = (子类类型)父类引用。
只能强转父类的引用,不能强转父类的对象。
public class test {
public static void main(String[] args) {
Animal animal = new Cat();
Object obj = new Cat();
// animal.catchMouse; 不能调用,因为在编译阶段,能调用那些成员,是由编译类型来决定的
//向下转型就可以调用:子类类型 引用名 = (子类类型)父类引用
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
要求父类的引用必须指向的是当前目标类型的对象。
可以调用子类类型中所有的成员。
OK,本篇文章就到此结束了,非常感谢你能看到这里,所以如果你觉得这篇文章对你有帮助的话,请点一个大大的赞,支持一下博主,若你觉得有什么问题或疑问,欢迎私信博主或在评论区指出~