public可以理解为一个人的外貌特征,谁都可以看见, default是包访问权限,是什么都不写的默认访问权限, protected一般主要是用在继承当中, private是只有自己知道,其他人都不知道自己的信息。
我们希望类要尽量做到封装,隐藏内部实现细节,只暴露必要的信息给类的使用者,因此我们在使用的时候尽可能的使用必要严格的访问权限,如果一个方法能用 private就尽量不要用 public,一般来说,我们将类中的字段设为 private将方法设为 public ,但具体的使用还是得结合实际情况认真选择,尽量避免滥用访问权限。
java复制代码
public class Student {
private String name;
private String gender;
private int age;
public void printStu() {
this.name = "jake";
this.age = 12;
this.gender = "man";
System.out.println("name:"+this.name);
System.out.println("age:"+this.age);
System.out.println("gender:"+this.gender);
}
public static void main(String[] args) {
Student s1 = new Student();
s1.initStu();
}
}
就比如我们上面这段代码,我们定义的姓名,年龄,性别都是 private 的,但是在类外,我们可以通过定义的 public 的方法来访问 private 的字段,这样可以使我们的程序更具健全性和安全性
三.继承
1.为什么要有继承
如果我们要用Java来描述猫和狗的话,那我们就需要设计俩个类
java复制代码
class Dog {
public String name;//名字
public int age;//年龄
public float weight;//重量
// 狗的行为
public void eat() {
System.out.println(name + "正在吃...");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
}
class Cat {
public String name;//名字
public int age;//年龄
public float weight;//重量
// 猫的行为
public void eat() {
System.out.println(name + "正在吃...");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}
class Animal {
public String name;//名字
public int age;//年龄
public float weight;//重量
public void eat() {
System.out.println(name + "正在吃饭");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
}
class Dog extends Animal {
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
}
class Cat extends Animal{
void mew() {
System.out.println(name + "喵喵喵~~~");
}
}
我们可以发现,代码整体比之前精简了许多,但是完成的功能却是一样的
注意:
子类会将父类中的成员变量或者成员方法继承到子类中了
子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
4.父类成员访问
在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?
子类中访问父类的成员变量
子类和父类不存在同名成员变量:
java复制代码
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
在这种情况下,我们是可以正常访问我们想访问的字段的
2. 子类和父类成员存在变量同名:
java复制代码
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100; // 访问子类自己新增的a
b = 101; // 访问子类自己新增的b
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 访问子类自己的methodB()
methodA(); // 访问父类继承的methodA()
// methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()
}
}
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的method(int)方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
}
}
public class Base {
int a;
int b;
public void methodA() {
System.out.println("Base中的methodA()");
}
public void methodB() {
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base {
int a; // 与父类中成员变量同名且类型相同
char b; // 与父类中成员变量同名但类型不同
// 与父类中methodA()构成重载
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 与基类中methodB()构成重写(即原型一致,重写后序详细介绍)
public void methodB() {
System.out.println("Derived中的methodB()方法");
}
public void methodC() {
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
// 注意:this是当前对象的引用
// 访问父类的成员变量时,需要借助super关键字
// super是获取到子类对象中从基类继承下来的部分
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的基类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
super.methodB(); // 访问基类的methodB()
}
}
在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可,需要注意的一点是, super 和 this 一样,只能在非静态方法中使用
6.子类构造方法
父子父子,先有父再有子,即:子类对象构造时,需要先调用父类构造方法,然后执行子类的构造方法
java复制代码
public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
// 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
// 并且只能出现一次
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
在Java中,我们也支持多种继承方式,但是值得注意的是,与 C++ 不同的是,Java不允许多继承的方式存在,也就是说,在Java中,一个类,不允许同时继承多个类;即便是允许多层继承,我们一般也不建议进行超过3层的继承,就像递归一样,多层的嵌套往往是不利于我们编程效率的,在遇见这种情况的时候,我们一般就得思考别的办法对代码进行重构
public static void fun(Animal animal) {
animal.eat();
}
public static void main(String[] args) {
Cat cat = new Cat("布偶",3);
Dog dog = new Dog("哈士奇",2);
fun(cat);
fun(dog);
}
我们可以看见输出结果,俩个对象都访问的是父类中的eat方法,都是吃食物
第三种方式:通过返回值
我们再这里新建俩个方法
java复制代码
public static Animal fun1(Animal animal) {
return new Cat("布偶",3);
}
public static Animal fun2(Animal animal) {
return new Dog("哈士奇",2);
}