Java-面向对象进阶

目录

1.static静态变量

2.静态方法和工具类

3.static注意事项

4.继承

5.多态

6.包

7.final关键字

8.权限修饰符

9.代码块

10.抽象类和抽象方法

11.接口

12.内部类


1.static静态变量

被static修饰的成员变量,叫做静态变量。

特点:被该类所有对象共享;

不属于对象,属于类;

随着类的产生而存在,优先于对象存在;

调用方式:类名调用(推荐);对象名调用。

e.g:

package csdn;

public class Student {
    String name;
    static String teacher_name;//一个班的学生,共享一个老师

    Student(String name){
        this.name=name;
    }
    public void show_info(){
        System.out.print("学生:"+name+" ");
        System.out.println("老师:"+teacher_name);
    }
}

In a word:当一个类的对象需要共享一个成员变量时,可以使用static修饰该变量,使之成为静态变量,供所有对象共享

2.静态方法和工具类

特点:多用在测试类和工具类,JavaBean很少用到。

调用方式:类名调用(推荐);对象名调用。

PS:工具类是用来帮助做一些事情的类,在这类需要私有化构造方法(外界创建工具类的对象没有意义),方法定义为静态。

e.g:创建数组工具类,加以测试;

package csdn;

public class ArrayUtil {
    //私有化构造方法
    private ArrayUtil(){

    }
    //打印工具
    public static String PrintArray(int arr[]){
        StringBuilder sb=new StringBuilder();
        sb.append("[");
        for(int i=0;i
package csdn;

public class ArrayUtilTest {
    public static void main(String[] args) {
        //方法类无法外界创建对象,直接使用类名调用成员方法。
        int arr[]={1,2,3,4,5};
        System.out.println(ArrayUtil.PrintArray(arr));//[1,2,3,4,5]

        System.out.println(ArrayUtil.PrintAverage(arr));//3

    }
}

3.static注意事项

静态方法只能访问静态变量和静态方法;

静态方法中没有this关键字

4.继承

①.关键字extends,可以让一个类和另一个类建立起继承关系。

e.g:

public class Student extends Person{}

Student称子类(派生类),Person称父类(基类)

好处:子类中重复的代码可以提取到父类中,提高代码复用性;

           子类可以在父类的基础上增加功能。

package csdn;

public class Person {
    private String name;
    private int age;
}
class Student extends Person{
    public void Study(){
        System.out.println("学生学习");
    }
}
class Teacher extends Person{
    public void Teach(){
        System.out.println("老师授课");
    }
}

②.继承的特点

Java只支持单继承(一个子类只继承一个父类),不支持多继承,但支持多层继承

(子类A可以继承父类B,父类B可以继承父类C)。

每个类都直接或间接继承于Object(虚拟机自动)。

public class A{}
//其实是
public class A extends Object{}

子类能访问父类的哪些内容:

构造方法 非私有 不可继承 私有 不可继承
成员变量 非私有 可继承 私有 可继承
成员方法 非私有 可继承 私有 不可继承

③.继承中成员变量的访问特点

就近原则,xxx从局部位置开始找,到本类成员位置找,最后到父类成员位置找。

this.xxx从本类成员位置开始找,到父类成员位置找。

super.xxx直接到父类成员位置找。

public class Test {
    public static void main(String[] args) {
        Er e=new Er();
        e.Print();
    }
}
class Die{
    String name="爹";
}
class Er extends Die{
    String name="儿子";
    public void Print(){
        String name="儿中儿";
        System.out.println(name);//儿中儿
        System.out.println(this.name);//儿子
        System.out.println(super.name);//爹
    }
}

④.继承中成员方法的访问特点

方法重写:当父类中的方法不满足子类的要求,就需要重写方法;@Override放在重写方法上面,校验子类重写方法语法;

public class Test02 {
    public static void main(String[] args) {
        exchangeStudents es=new exchangeStudents();
        es.show_me();
    }
}
class Students{
    public void eat(){
        System.out.println("吃河道果实");
    }
    public void drink() {
        System.out.println("喝腐败药水");
    }
}
class exchangeStudents extends Students{
    public void show_me(){
        this.eat();//吃探照果实
        this.drink();//喝复用型药水
        super.eat();//吃河道果实
        super.drink();//喝腐败药水
    }
    @Override
    public void eat(){
        System.out.println("吃探照果实");
    }
    public void drink(){
        System.out.println("喝复用型药水");
    }
}

方法重写注意事项:

重写的方法名,形参列表要和父类一样;

重写的方法访问权限子类必须大于等于父类(不设权限

重写方法的返回值子类必须小于等于父类;

私有方法不能重写;

静态方法不能重写;

(未添加到虚方法表的方法不能重写);

(重写的本质:覆盖虚方法表中的方法)。

⑤.继承中构造方法的访问特点

父类的构造方法不会被子类继承;子类的所有构造方法默认先访问父类的无参构造,再执行自己。

子类的构造方法第一句默认super();不写也存在且必须在第一行。

子类想调用父类的有参构造时必须加super。

e.g:

public class Test {
    public static void main(String[] args) {
        Students s=new Students("王德发",19);
        s.Print();
    }
}
class Person {
    String name;
    int age;
    public Person(){
        System.out.println("父类的无参构造");
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
}
class Students extends Person{
    public Students(){
        super();
        System.out.println("子类的无参构造");
    }
    public Students(String name,int age){
        super(name,age);
    }
    public void Print(){
        System.out.println(this.name);
        System.out.println(this.age);
    }
}

5.多态

①.多态就是对象的多种形态

前提:有继承关系/实现关系

          有父类引用指向子类对象

          有方法的重写

好处:使用父类对象为参数,可以接收所有子类对象。

public class Test {
    public static void main(String[] args) {
        Student s=new Student();
        s.setName("王德发");
        s.setAge(19);
        Teacher t=new Teacher();
        t.setName("墨菲特");
        t.setAge(20);

        show(s);//学生叫:王德发年龄19
        show(t);//老师叫:墨菲特年龄20
    }
    //父类对象作参数
    public static void show(Person p){
        p.Print();
    }
}
class Person {
    String name;
    int age;


    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void Print(){
        System.out.println(this.name+" "+this.age);
    }
}
class Student extends Person{
    @Override
    public void Print(){
        System.out.println("学生叫:"+this.name+"年龄"+this.age);
    }
}
class Teacher extends Person{
    @Override
    public void Print(){
        System.out.println("老师叫:"+this.name+"年龄"+this.age);
    }
}

②.

调用成员变量时:编译看左边(父类),运行看左边(子类);

调用成员方法时:编译看左边,运行看右边;

public class Test {
    public static void main(String[] args) {
        //左          右
        Animal a=new Dog();
        //调用成员变量,javac编译时看左边,如果左边(父类)有该变量,编译成功,反之编译失败
        //javac运行时看左边,实际获取的就是父类中该成员变量的值。
        System.out.println(a.name);//动物
        //调用成员方法,javac编译时看左边,如果左边(父类)有该方法,编译成功,反之编译失败
        //javac运行时看右边,实际获取的是子类中的成员方法
        a.Print();//这是个狗
    }
}
class Animal{
    String name="动物";

    public void Print(){
        System.out.println("这是个动物");
    }
}
class Dog extends Animal{
    String name="狗";
    @Override
    public void Print(){
        System.out.println("这是个狗");
    }

}

③多态的优势和缺陷

优势:定义方法时,使用父类作参数,可以接收所有子类,便利;

          在多态形式下,子类可以实现解耦合,便于维护。

弊端:不能使用子类独有的功能。

解决方案:转换成子类类型,从而调用子类独有的功能。

public class Test {
    public static void main(String[] args) {
        Animal a=new Dog();
        //a.EatRou();报错
        //原因:多态情况下调用成员方法,从左边找,父类中未定义Eat函数,故javac编译报错
        //解决:类型转换:
        Dog d = (Dog)a;
        d.EatRou();
    }
}
class Animal{
    public void Print(){
        System.out.println("动物吃饭");
    }
}
class Dog extends Animal{
    public void EatRou(){
        System.out.println("狗吃小肉干");
    }

}
class Cat extends Animal{
    public void EatYu(){
        System.out.println("猫吃小鱼干");
    }
}

PS:instanceof关键字 a  instance  typeB:判断a是否为B类型,是返回true否返回false。

有时为了避免类型转换出错,会使用instanceof先判断再进行强转。

6.包

包就是文件夹,用来管理不同功能的Java类。

导包规则

使用同一包中的类,不需要导包;

使用java.lang包中的类(如String),不需要导包;

使用两个包中的同名类,需要使用全类名。

7.final关键字

修饰方法时:表示不能被重写

修饰类时:表示不能被继承

修饰变量时:表示常量,只能被赋值一次

常量命名规范:单个单词:全部大写;多个单词:全部大写,用下划线隔开

细节:final修饰基本数据类型(如:int),表示数据值不能改变;

           final修饰引用数据类型(如:数组),表示数据地址值不能改变,但存储的数值可以改变。

8.权限修饰符

范围:private<默认

同一类中 同一个包中其他类 不同包下的子类 不同包下的无关类
private
默认
protected
public

实际开发中使用频繁的是private和public

9.代码块

①局部代码块

public class Code {
    public static void main(String[] args) {
        {
            int a=10;
        }//在这里a已经从内存中消失
        System.out.println(a);//a的生命周期已结束,无法访问
    }
}

是为了节省内存,提前结束变量生命周期

现在已经用不到,计算机内存不需要节省那么点空间。

②构造代码块

写在成员位置,把多个构造方法重复的代码提取出来,优先于构造方法执行。

public class Code {
    public static void main(String[] args) {
        Students s=new Students();
        //这是构造代码块
        //空参构造
        Students s_1=new Students("王德发",19);
        //这是构造代码块
        //有参构造
    }
}
class Students{
    String name;
    int age;
    {
        System.out.println("这是构造代码块");
    }
    public Students() {
        System.out.println("空参构造");
    }

    public Students(String name, int age) {
        System.out.println("有参构造");
        this.name = name;
        this.age = age;
    }
}

这种方法现在也不常用,因为不灵活,构造代码块必定执行,且优先于构造方法执行。

更常用将多个构造方法中的重复代码提取成一个方法。

③静态代码块

static{}

特点:随着类的加载而执行,且只执行一次。用于加载类时的初始化

public class Code {
    public static void main(String[] args) {
        Students s=new Students();
        //这是构造代码块
        //空参构造
        Students s_1=new Students("王德发",19);
        //有参构造
    }
}
class Students{
    String name;
    int age;
    static {
        System.out.println("这是构造代码块");
    }
    public Students() {
        System.out.println("空参构造");
    }

    public Students(String name, int age) {
        System.out.println("有参构造");
        this.name = name;
        this.age = age;
    }
}

10.抽象类和抽象方法

将共性的方法抽取到父类后,如果不能确定具体的方法体,就可以定义为抽象方法;

如果一个类中存在抽象方法,这个类必须声明为抽象类。

定义格式:

抽象方法:public abstract 返回值类型 方法名(参数列表);

抽象类:public abstract class 类名{}

public abstract class Abstract {
    public abstract void Work();
}

注意事项:Ⅰ抽象类不能实例化(创造对象);

                  Ⅱ抽象类中不一定有抽象方法,有抽象方法的一定是抽象类;

abstract class Animals{
    public void Print(){
        System.out.println("动物");
    }
}

                  Ⅲ可以有构造方法;

                  Ⅳ抽象类的子类要么重写抽象类所有抽象方法,要么该子类也是抽象类。

11.接口

①接口就是一种对行为的抽象。

接口用关键字interface定义

public interface 接口名{}

接口不能实例化

接口和类之间是实现关系,用关键字implements实现

public class 类名 implements 接口名{}

接口的子类(实现类)要么重写接口的所有抽象方法,要么该子类是抽象类

接口的子类可以多实现

public class 类名 implements 接口1,接口2{}

还可以在继承父类的同时实现多个接口

public class 子类名 extends 父类名 implements 接口1,接口2{}

e.g:创建Person类,子类为中国人,外国人,假人;

因为假人没有Speak行为,故Speak行为需写成接口,供中国人和外国人调用。

public class Test {
    public static void main(String[] args) {
        Chinese c=new Chinese("王德发",19);
        System.out.println("名字:"+c.getName()+"年龄:"+c.getAge());
        c.speak();
        c.food();

        dummy d=new dummy("目标假人",190);
        System.out.println("名字:"+d.getName()+"年龄:"+d.getAge());
        d.food();
    }
}
abstract class Person {
    private String name;
    private int age;


    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public abstract void food();
}
interface Speak {
    public abstract void speak();
}
class Chinese extends Person implements Speak{

    public Chinese() {
    }

    public Chinese(String name,int age) {
        super(name,age);
    }

    @Override
    public void food() {
        System.out.println("吃饺子");
    }

    @Override
    public void speak() {
        System.out.println("讲汉语");
    }
}
class foreigners extends Person implements Speak{
    public foreigners(){

    }
    public foreigners(String name,int age){
        super(name,age);
    }
    @Override
    public void food() {
        System.out.println("吃比萨");
    }

    @Override
    public void speak() {
        System.out.println("讲外语");
    }
}
class dummy extends Person{
    public  dummy(){

    }
    public dummy(String name,int age){
        super(name,age);
    }
    @Override
    public void food() {
        System.out.println("吃伤害");
    }
    //假人没有Speak行为
}

②接口中成员特点

成员变量只能是常量,默认 public static final

没有构造方法

成员方法只能是抽象方法,默认public abstract

③JDK8接口中新增的方法

JDK7之前接口中只能写抽象方法;

JDK8可以定义有方法体的方法;

JDK9可以定义私有方法。

默认方法:public default 返回值类型 方法名(){}

注意:默认方法不是抽象类,不强制重写。如果要重写,重写时去掉default;

public可以省略,default不能省略;

静态方法:public static 返回值类型 方法名(){}

注意:静态方法只能用接口名调用;

public可以省略,static不能省略。

④接口应用:

接口代表规则,是行为的抽象。想让哪个类拥有这个行为,就让这个类实现对应的接口;

当一个方法的参数是接口,可以传递所有接口的实现类,这种方式称为接口的多态。

⑤适配器设计模式

当一个接口中抽象方法过多,而我们只需要用到一部分,就可以使用适配器设计模式;

书写步骤:

编写中间类XXXAdapter实现对应接口,对接口中的抽象方法全部进行空实现,让真正的实现类继承中间类,重写需要的方法,为了避免其他类创造中间类的对象,中间适配器类需要用abstract修饰。

12.内部类

①内部类表示的事物是外部类的一部分,内部类单独出现没有意义。

内部类可以直接访问外部类的成员,包括private修饰的;

外部类不能直接访问内部类的成员,如果想访问,必须创建对象。

e.g:引擎和汽车的关系

public class Car {
    String name;
    int age;
    String brand;
    public void show(Car this){
        System.out.println("车辆年限:"+this.age);
        Engine e=new Engine();//外部类想访问内部类成员,需要创建对象
        System.out.println("引擎寿命:"+e.engineage);
    }
    class Engine{
        String enginename;
        int engineage;

        public void show(){
            System.out.println("车辆品牌:"+brand);
            System.out.println("引擎型号:"+enginename);
        }
    }
}

②内部类的分类

成员内部类:写在成员位置,属于外部类的成员

获取内部类成员的方法:

Ⅰ.在外部类编写对外提供内部类成员的方法

Ⅱ.外部类名.内部类名 对象名 = new 外部类名().new 内部类名();

public class Test {
    public static void main(String[] args) {
        Outer.Iner oi=new Outer().new Iner();
        oi.show();//10
    }
}
class Outer{
    int a=10;
    class Iner{
        public void show(){
            System.out.println(a);
        }
    }
}

外部类成员变量和内部类成员变量重名时,怎么在内部类访问

class Outer{
    private int a=10;
    class Iner{
        private int a=20;
        public void show(){
            int a=30;
            System.out.println(a);//30
            System.out.println(this.a);//20
            System.out.println(Outer.this.a);//10
        }
    }
}

局部内部类

将内部类定义在方法里就叫局部内部类。

外部无法直接使用,要在方法内创建对象方可使用

局部内部类可以直接访问外部类的成员,也可访问方法内的局部变量

静态内部类

当成员内部类用static修饰时,就叫静态内部类,静态内部类只能访问外部类的静态成员变量和静态成员方法,如果想访问非静态的需要创建对象。

创建静态内部类对象:外部类名.内部类名 对象名=new 外部类名.内部类名();

调用静态方法:外部类名.内部类名.方法名();

public class Test {
    public static void main(String[] args) {
        Outer.Iner oi=new Outer.Iner();
        oi.show1();//静态内部类的非静态方法
        Outer.Iner.show2();//静态内部类的静态方法
    }
}
class Outer{
    static class Iner{
        public void show1(){
            System.out.println("静态内部类的非静态方法");
        }
        public static void show2(){
            System.out.println("静态内部类的静态方法");
        }
    }
}

匿名内部类

匿名内部类本质就是隐藏了类名的内部类

格式:new 类名/接口名(){

重写方法;

}

绿色的部分其实才是匿名内部类,加上new 类名/接口名后他的本质应该是一个对象,和类名/接口名的关系应该是继承/实现。

e.g:直接将匿名内部类作为对象传给方法。

public class Test {
    public static void main(String[] args) {
        show(
                new Animal(){
                    @Override
                    public void eat(){
                        System.out.println("狗吃骨头");
                    }
                }
        );//狗吃骨头
    }

    public static void show(Animal a){
        a.eat();
    }
}
abstract class Animal{
    public abstract void eat();
}

In a word,匿名内部类整体是一个类的对象或者一个接口的实现类对象。

使用场景:

当方法的参数是类/接口时,可以传递这个类的子类对象/实现类对象,如果只需要执行一次,就可以使用匿名内部类简化代码。

你可能感兴趣的:(Java,java,开发语言)