JavaSe基础:面向对象3
1. 权限修饰符
权限修饰符的作用是指定内容能够被使用的范围,具体如下:
本类 | 同包类 | 不同包子类 | 不同包下的其他类 | |
---|---|---|---|---|
私有的private | √ | |||
默认的default | √ | √ | ||
受保护的protected | √ | √ | √ | |
公共的public | √ | √ | √ | √ |
注:
- 使用最多的是private和public
- 能够修饰类的权限修饰符:public,default(默认的省略不写)
- 都是成员修饰符,只能修饰成员,不能修饰局部
- 在不同包下的子类,如果想要使用父类中被protected修饰的成员,需要通过继承关系使用(直接在子类使用有权限的父类成员,或者通过子类对象使用),不能通过父类对象使用
例:
//测试本类下
public class ModifierTest {
//静态变量
private static String privateTest = "private";
static String defaultTest = "default";
protected static String protectedTest = "protected";
public static String publicTest = "public";
//成员变量
private String privateTest01 = "private";
String defaultTest01 = "default";
protected String protectedTest01 = "protected";
public String publicTest01 = "public";
public static void main(String[] args) {
//测试静态变量
System.out.println(privateTest);
System.out.println(defaultTest);
System.out.println(protectedTest);
System.out.println(publicTest);
//测试成员变量
ModifierTest m1 = new ModifierTest();
System.out.println(m1.privateTest01);
System.out.println(m1.defaultTest01);
System.out.println(m1.protectedTest01);
System.out.println(m1.publicTest01);
}
}
//测试同包下
public class ModifierTest02 {
public static void main(String[] args) {
//测试静态变量
//System.out.println(ModifyTest.privateTest); private修饰的无法使用
System.out.println(ModifierTest.defaultTest);
System.out.println(ModifierTest.protectedTest);
System.out.println(ModifierTest.publicTest);
//测试成员变量
ModifierTest m2 = new ModifierTest();
//System.out.println(m2.privateTest01); private修饰的无法使用
System.out.println(m2.defaultTest01);
System.out.println(m2.protectedTest01);
System.out.println(m2.publicTest01);
}
}
//测试不同包下子类
public class ModifierTest03 extends ModifierTest {
public static void main(String[] args) {
//测试静态变量
//System.out.println(privateTest); private修饰的无法使用
//System.out.println(defaultTest); default修饰的无法使用
System.out.println(protectedTest);
System.out.println(publicTest);
//测试成员变量
ModifierTest03 m3 = new ModifierTest03();
//System.out.println(m3.privateTest01); private修饰的无法使用
//System.out.println(m3.defaultTest01); default修饰的无法使用
System.out.println(m3.protectedTest01);
System.out.println(m3.publicTest01);
}
}
//测试不同包下其他类
public class ModifierTest04 {
public static void main(String[] args) {
//测试静态变量
//System.out.println(ModifyTest.privateTest); private修饰的无法使用
//System.out.println(ModifierTest.defaultTest); default修饰的无法使用
//System.out.println(ModifierTest.protectedTest); protected修饰的无法使用
System.out.println(ModifierTest.publicTest);
//测试成员变量
ModifierTest m4 = new ModifierTest();
//System.out.println(m4.privateTest01); private修饰的无法使用
//System.out.println(m4.defaultTest01); default修饰的无法使用
//System.out.println(m4.protectedTest01); protected修饰的无法使用
System.out.println(m4.publicTest01);
}
}
2. 方法的重写Override
重写是方法的特性,可以重新定义方法体,需要满足以下条件:
- 不同的两个类
- 继承关系
- 方法签名(方法名+参数列表)相同
应用场景:在子类继承父类后,继承了一系列功能方法,有些功能的实现不满意,可以进行功能的重写。
子类一旦重写方法,子类对象调用的时候,采用就近原则;子类对象调用功能时,子类存在找子类,子类没有找父类。
注:子类一旦重写父类中的方法,就会对父类方法进行屏蔽
不能被重写的方法:
- 被private关键字修饰的方法不能被重写
- 被final关键字修饰的方法不能被重写
- 被static关键字修饰的方法不能被重写,当子类中出现与父类静态方法同名的方法时,子类的同名方法也要是静态的,否则会报错,但是不是重写方法
例:
//测试方法的重写
public class OverrideTest {
public static void main(String[] args) {
Zi zi = new Zi();
zi.speak();
}
}
//定义父类
class Fu{
public void speak(){
System.out.println("我是父类");
}
}
//定义子类
class Zi extends Fu{
//方法的重写
@Override
public void speak(){
System.out.println("我是子类");
}
}
3. 多态Polymorphism
多态是一种事物的多种形态或多种表现形式,多态的最终体现是父类的引用指向子类的对象。多态的前提是继承,优点是可以让程序变得更加灵活,便于后期维护。
多态使用过程中,当父类类型的引用调用成员时,成员变量和成员方法编译看父类,成员方法运行找子类。当通过父类的引用调用成员方法时,如果子类有重写方法就调用重写的,如果没有就找父类。
例:
//测试多态
public class PolymorphismTest {
public static void main(String[] args) {
//多态的体现
FuLei fu = new ZiLei();
System.out.println(fu.name);//打印父类的name属性
fu.test();//调用子类的重写方法
}
}
//定义父类
class FuLei{
String name = "张三";
public void test(){
System.out.println("我是父类");
}
}
//定义子类
class ZiLei extends FuLei{
String name = "李四";
@Override
public void test(){
System.out.println("我是子类");
}
}
4. 类型转换Cast
引用数据类型的转型,分为以下两种:
- 向上转型:即自动类型提升,多态就是向上转型的体现
- 向下转型:即强制类型转换,具体语法是 “小范围类型 变量 = (小范围类型) 大范围类型的数据”
注:
- 多态引用不能调用子类中独有的方法,对子类新增功能不可见
- 如果想要调用子类的独有方法,需要向下转型
- 如果向下转型想要保证不出现类型转换异常,可以使用instanceof进行提前判断,instanceof是用来判断前面的引用是否指向后面类型的对象,或者是否指向后面类型子类的对象,如果是返回true,不是返回false
例:
//测试类型转换
public class CastTest {
public static void main(String[] args) {
Father father = new Son1();
System.out.println(father.name);//父亲
father.speak();//我是大儿子
//判断引用是否为Son1类对象
if (father instanceof Son1){
Son1 son1 = (Son1) father;
System.out.println(son1.name);//大儿子
son1.speak();//我是大儿子
son1.play();//打篮球
}
//测试instanceof的使用
System.out.println(father instanceof Father);//true
System.out.println(father instanceof Son1);//true
System.out.println(father instanceof Son2);//false
}
}
//定义父类
class Father{
String name = "父亲";
void speak(){
System.out.println("我是父亲");
}
}
//定义子类1
class Son1 extends Father{
String name = "大儿子";
//方法重写
@Override
void speak(){
System.out.println("我是大儿子");
}
void play(){
System.out.println("打篮球");
}
}
//定义子类2
class Son2 extends Father{
String name = "二儿子";
//方法重写
@Override
void speak(){
System.out.println("我是二儿子");
}
void play(){
System.out.println("踢足球");
}
}
5. Object类
object类是java的老祖宗类,存在于java.lang包下,不需要导包,是java中所有类的父类,有两个重点方法,一个是equals方法,一个是toString方法。
5.1 equals方法
equals方法是用来比较两个对象是否相等的方法(默认是使用==进行比较,比较的是对象地址),如果想要实现比较对象内容而非地址值时,需要在子类中重写equals方法,实现比较成员属性的值。
注:
- 通过java实现功能就是为了处理生活中的业务,会以生活中具体的逻辑考虑问题,认为两个对象如果所有成员属性的值都想等,就应该是一个对象
- 在java中只要通过new关键字创建的对象,无论成员属性值是否相等,地址都不相等,如果比较地址的话都不相等,所以使用引用数据类型对象的时候,不让它默认比较地址,手动让它实现比较内容
例:
//测试重写equals方法
public class EqualsOverride {
public static void main(String[] args) {
Person p1 = new Person("张三",18);
Person p2 = new Person("张三",18);
//比较两个对象的地址
System.out.println(p1 == p2);//false
//重写equals方法变成比较两个对象的属性
System.out.println(p1.equals(p2));//true
}
}
//定义类
class Person{
public String name;
public int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写equals方法
@Override
public boolean equals(Object obj){
String str1 = this.name;
int a1 = this.age;
if(obj instanceof Person){
String str2 = ((Person) obj).name;
int a2 = ((Person) obj).age;
if (str1.equals(str2) && a1 == a2){
return true;
}
}
return false;
}
}
5.2 toString方法
toString方法是以字符串的形式表示当前对象。object类中的toString方法默认返回当前对象类型的包名.类名@十六进制。如果想要打印对象的成员变量的值不想打印对象地址,需要在子类中对toString方法进行重写。
注:
- 当打印一个对象的引用的时,默认会调用toString,打印的是当前对象调用了toString之后的返回值
- 以后所定义的javabean规范:默认提供一个toString以及equals方法的重写
例:
//测试重写toString方法
public class ToStringOverride {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "张三";
stu.age = 19;
System.out.println(stu);//默认调用toString方法 Student{张三,19}
}
}
//定义类
class Student{
public String name;
public int age;
//重写toString方法
@Override
public String toString() {
return "Student{"+name+","+age+"}";
}
}
6. Abstract类
被abstract修饰的类为抽象类,被abstract修饰的方法为抽象方法。抽象方法可以没有方法体,但必须存在于抽象类中。
注:
- 抽象类不能够实例化
- 抽象方法必须存在抽象类中
- 抽象类中可以存在抽象方法,可以存在普通的具体方法,可以存在成员,构造器
- 抽象方法必须要被重写才能使用
- 抽象方法只要被重写就可以使用,不需要再次重写,可以根据需求进行重写
- 抽象类使用:通过具体子类的对象调用。如果是普通的子类,需要重写所有抽象方法以及按需新增;如果是抽象子类,按需重写抽象方法以及按需新增
- abstract不能与private,static,final,native关键字同时存在
例:
//测试抽象类
public class TestAbstract {
public static void main(String[] args) {
Employee e = new Employee();
e.work();
e.work1();
}
}
//定义抽象类
abstract class Job{
abstract void work();
}
//定义抽象类继承抽象类
abstract class Designer extends Job{
abstract void work1();
}
//定义类继承抽象类
class Employee extends Designer{
//重写抽象方法
@Override
void work() {
System.out.println("我是做设计的员工");
}
//重写抽象方法
@Override
void work1() {
System.out.println("我是做建筑设计的员工");
}
}