目录
4、向下转型 (将父类引用强制转换为子类引用)(要发生向下转型,首先要发生向上转型)
一、类的访问修饰符
从小到大依次为:
private(私有,当前类的内部可见) < default(包访问权限,当前包的内部可见,不包含子包 ,同级目录下可见)< protected (继承访问权限 ,不同包的有继承关系的类之间可见) < public (当前项目可见)
java中的“包”就是操作系统的文件夹,声明一个包使用package关键字,若存在多个文件夹的嵌套,使用“.”分隔,如 package www.java.se
IDEA显示空包:

类的全名称:包名.类名(包的存在就是为了解决类同名的问题)
二、如何导入某个包中的某个类?(import 导入类)
1、import语句:
只能导入相关包中的某个具体的类

2、导入包中的若干类:
import java.包名称.*(一般不推荐,可能存在歧义)
如:import java.util.* //将整个util包下的所有类按需加载,此时导入的还是类,而不是把整个util文件夹导入

当程序中用到了两个相同名称的类
(1)使用类的全名称
(2)明确指定导入的是哪个包下的哪个类
3、静态导入:
import static 可以导入包中的静态方法和静态属性(不推荐,还是使用类名.方法名称/属性名称 访问类中的静态域)

4、常见的系统包
(1)java.lang :JDK的基础类,System,String,Object都在这个包下,JDK1.1后这个包下的所有类自动导入
(2)java.lang.reflect:反射开发包
(3)java.util :工具包(集合类都在这个包下,Arrays,LinkedList,HashMap)
(4)java.io :I/O开发包,文件的读取和写入
(5)java.net:网络编程开发包,Socket
(6)java.sql :数据库开发包
三、封装
封装:保护性和易用性
封装有很多表现形式,private实现属性和方法的封装只是其中一种。
private(私有的):被private 修饰的属性和方法,只在当前类可见,出了类的{ },对外就完全隐藏了,外部不知道有其存在。
//公共访问权限,主类
public class privateTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.setPassword();
System.out.println("修改后的密码为:");
System.out.println(bank.getPassword());
System.out.print("银行卡号为:");
System.out.println(bank.getCardNum());
System.out.print("银行卡余额为:");
System.out.println(bank.getBalance());
}
}
//缺省修饰符,包访问权限
class Bank{
//私有属性,只在Bank这个类内部可见
private int cardNum;//卡号,只可取
private double balance;//余额,只可取
private String password = "123456";//密码,既可取也可改
//要在类的外部去使用这些私有属性,需要使用类提供的getter()和setter()方法
//alt + insert 快速生成getter()和setter()方法
//shift+A全选
//get + 属性名称 = 方法命名
public int getCardNum() {
return cardNum;
}
public double getBalance() {
return balance;
}
public String getPassword() {
return password;
}
//设置新密码
public void setPassword() {
//验证旧密码(安全性)
Scanner scan = new Scanner(System.in);
int count = 0;
while(true){
System.out.println("请输入您的旧密码:");
String oldPass = scan.nextLine();
count ++;
if (oldPass.equals(password)) {
System.out.println("验证成功,请输入您的新密码:");
String newPass = scan.nextLine();
password = newPass;
System.out.println("密码修改成功");
break;
}else{
System.out.println("密码错误,请查证后再试!");
if(count == 3){
System.out.println("验证次数过多,银行卡已锁定");
break;
}
}
}
}
}

四、继承
1、继承:
当类和类之间满足一个类 is a 另外一个类,一定存在继承关系。当一个类继承了另一个类,另一个类中所有的属性和方法子类就天然具备了。 Java中使用extends表示类的继承。
如:Bird is an Animal;
Dog is an Animal;
Bird、 Dog都是 Animal 的子类。
2.继承的规则
(1)要能使用继承,前提必须满足类之间的 is a 关系
Person extends Dog{} ×
Person is not a Dog
(2)一个子类只能使用extends继承一个父类(单继承)。

Java中不允许多重继承,extends 后面只能跟一个父类,但允许多层继承。

(3)子类会继承父类的所有属性和方法(类属性、类方法以及成员属性、成员方法)(显示继承(public属性和方法可以直接使用)和隐式继承(private 属性和方法,子类也继承这类属性和方法,但是无法直接使用))
public class Animal {
public String name;
//age这个属性只在当前类的内部可见,子类其实也继承了,但是没法直接使用
private int age;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void eat(String name, String food){
this.name = name;
System.out.println( name+"正在吃" +food);
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat("小王","蔬菜");
Dog dog = new Dog();
dog.setAge(10);
System.out.println(dog.getAge());
dog.eat("花花","狗粮");
}
}
3、protected访问权限
语义:作用域同包下(不包含子包)的类之间(不管有无继承关系)以及不同包的有继承关系的类之间可见(但出了这个类,在不同包的其他类中则不可见)【只在当前包和子类的内部可见】。


4、继承的规则(产生子类对象之前,默认先产生一个父类对象)



5.super关键字
this关键字:表示当前对象的引用
(1)修饰属性,表示从当前类中找同名属性
this关键字表示从当前类寻找同名属性,若不存在,继续向上寻找父类中是否存在同名属性。
public class Person {
protected String name = "Person";
}
public class China extends Person {
protected String name = "China";
public void show(){
System.out.println(name);//相当于this.name 默认在当前类中寻找同名属性
//若没找到,才会向上寻找父类中的同名属性
}
public static void main(String[] args) {
China china = new China();
china.show();
}
}


(2)修饰方法(普通方法和构造方法)
(3)表示当前对象的引用
super关键字
(1)修饰属性,表示直接从父类中寻找同名属性。先从直接父类中去寻找同名属性,若不存在再向上寻找(爷爷类)

public class Animal {
protected String name = "Animal";
}
public class Person extends Animal {
protected String name = "Person";
}

若直接父类中没有同名属性,继续向上寻找。


不能使用super关键字直接调用父类private权限的属性
public class Animal {
protected String name = "Animal";
}
public class Person extends Animal{
private String name = "Person";
}
public class China extends Person{
protected String name = "China";
protected void print(){
System.out.println(super.name);
}
public static void main(String[] args) {
China china = new China();
china.print();
}
}
(2)修饰方法,表示直接从父类中去寻找方法
(2-1)修饰构造方法
super(父类构造方法的参数);
super();//直接父类的无参构造,可写可不写。若父类中不存在无参构造,则子类构造方法的首行必须使用super(有参构造)以显示调用。
若产生子类对象,默认先产生父类对象,若父类对象上还有基础,继续向上先产生祖类对象,最后产生子类对象。
public class Animal {
protected String name = "Animal";
public Animal(){
System.out.println("Animal类的无参构造");
}
}
public class Person extends Animal {
protected String name = "Person";
public Person(){
System.out.println("Person类的无参构造");
}
}

public class Person{
protected String name = "Person";
public Person(String name) {
this.name = name;
System.out.println("Person的有参构造");
}
}
public class China extends Person{
protected String name = "China";
public China(){
System.out.println("China的无参构造");
}
protected void print(){
System.out.println(super.name);
}
public static void main(String[] args) {
China china = new China();
}
}

public class Person {
protected String name ;
public Person(String name){
this.name =name;
System.out.println("Person类的有参构造");
}
}
public class China extends Person{
protected String name = "China";
public China(){
super("小羊");
System.out.println("China的无参构造");
}
protected void print(){
System.out.println(super.name);
}
public static void main(String[] args) {
China china = new China();
}
}

注意:在一个构造方法中,无法同时显式使用 this()和super(),因为这两个都要放在首行。


(2-2)修饰普通方法(直接从父类中寻找同名方法,和super修饰属性相同)
public class China extends Person {
protected String name = "China";
public China(){
super("小王");
System.out.println("China类的无参构造");
}
public void test(){
show();
}
public void show() {
System.out.println("China类的show方法");
}
public static void main(String[] args) {
China china = new China();
china.test();
}
}

(3)super 关键字不表示父类对象的引用
6.final 关键字(终结器)
(1)修饰属性表示属性值不能变,常量
(2)修饰类,表示这个类无法被继承
![]()

7.类之间的组合关系(has a)
class School {
Student student ;
Teacher teacher;
}
School has a student;
School has a teacher;
五、多态
1、多态性:
同一个引用调用同一个方法名,根据引用指向的不同的对象可以表现出不同的行为、特性
2、多态的向上转型(一定发生在有继承关系的类之间)
意义:参数统一化,降低使用者的使用难度。

其中子类对象不一定是直接子类,也可以是孙子类...只要是这个父类分支下的都可
有向上转型后,最顶端的父类引用就可以指代所有的子类对象。当最顶端的父类有一个新的子类时,便很容易扩展。
3.方法重写(override):
发生在有继承关系的类之间,子类定义了和父类除了权限不同,其他全都相同的方法,这样的一组方法称为方法重写。方法重写的返回值必须严格相同,向上转型除外。
判断调用的是谁的方法:不用看前半部分,看当前是通过哪个类new 的对象,若该类重写了该方法,则调用的一定是重写后的方法。
public class Animal {
public void eat(){
System.out.println("Animal类的eat方法");
}
}
public class Bird extends Animal{
public void eat(){
System.out.println("Bird类的eat方法");
}
}
public class Duck extends Bird {
public void eat(){
System.out.println("Duck类的eat方法");
}
}
public class Test {
public static void test(Animal animal){
animal.eat();
}
public static void main(String[] args) {
public static void main(String[] args) {
test(new Animal());
test(new Bird());
test(new Duck());
}
}
}

若子类没有重写方法,则向上搜索碰到第一个父类重写的方法就调用这个“最接近”的重写方法。

当发生重写时,子类权限 >= 父类权限才可以重写(private 权限不包含在内)
问:能否重写static方法?
不能。多态的本质就是调用了不同的子类对象,这些子类对象所属的类覆写相应的方法才能表现出不同的行为,static 方法和对象无关!方法重写只发生在普通方法中。
| 区别 | 方法重载(overload) | 方法重写(override) | |
| 1 | 范围 | 一个类 | 有继承关系的类之间 |
| 2 | 概念 | 方法名称相同、参数的类型及个数不同 | 方法名称、参数的类型及个数、返回值类型完全相同(或者向上转型的返回值类型) |
| 3 | 限制 | 没有权限要求 | 被覆写的方法的访问控制权限 >= 父类方法的权限 |
| 4 | static方法 | 没要求 | 不能重写static方法 |
向上转型发生的3种时机:
(1)方法传参
(2)引用赋值时
(3)方法返回值


4、向下转型 (将父类引用强制转换为子类引用)(要发生向下转型,首先要发生向上转型)
4.1向上转型语法
类名称 引用名称 = new 类实例();
引用名称 . 方法名称
能通过“.”访问的方法由类名称说了算,能访问的这些方法必须都在类中定义过,编译器会先在类中查找是否包含在指定方法。至于方法最终表现出的是哪个类的样子,由实例所在的方法说了算。
Animal animal = new Dog();
animal. 方法名称();
// 这个方法是否能调用,看Animal
// 表现出来的行为由具体new的子类说了算


4.2 向下转型的语法
子类名称 子类引用 = (子类名称)父类引用
Animai animal = new Dog(); //向上转型
Dog dog = (Dog) animal; //向下转型
何时使用向下转型?已知只有一个父类引用,但是要使用子类拓展的方法,此时就要把这个父类引用还原为子类引用(只有一个对象,并没有创建新的对象)

4.3要发生向下转型,首先要发生向上转型,毫不相干的两个类之间无法强转

4.4当发生向下转型时会有风险,类型转换异常,使用 instanceof关键字
引用名称 instanceof 类 ——>返回布尔值,表示该引用指向的本质是不是该类的对象
使用instanceof关键字的返回值搭配分支语句进行类型转换
public static void main(String[] args) {
Animal animal1 = new Animal();
Animal animal2 = new Dog();
if(animal1 instanceof Dog){
Dog dog = (Dog)animal1;
System.out.println(animal1 +"转型成功");
}else {
System.out.println(animal1 +"不是指向Dog()类型的引用");
}
if(animal2 instanceof Dog){
Dog dog = (Dog)animal2;
System.out.println(animal2 +"转型成功");
}else {
System.out.println(animal2 +"不是指向Dog()类型的引用");
}
}
本文详细介绍了Java面向对象编程的各个方面,包括类的访问修饰符、如何导入类、封装、继承以及多态。重点讲解了继承的规则、super关键字的应用、多态的向上转型和方法重写。此外,还探讨了protected访问权限和final关键字的作用。

1927

被折叠的 条评论
为什么被折叠?



