• java之面向对象


    1.面向对象与面向过程

    1.1面向过程(procedure oriented programming POP)

      刚开始接触C,它是一门面向过程思想的语言,写函数调函数是分析解决问题的步骤,就像小时候数学考试中的应用题一步一步算最后得到结果。

    1.2面向对象(object oriented programming OOP)

      后来接触到JAVA,它是一门面向对象思想语言,当时从面向过程转换到面向对象的思想经过好处时间才转过来,面向对象简单理解为 具体的事物,如(person,dog,cat...)那么

    这个对象能干什么用呢?我们分析一下,每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法)如(dog 状态 :颜色,品种,大小体重等等,行为:狗会跑,会啃骨头),java就是通过对象之间行为的交互来解决问题的。

    面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为。

    类是面向对象中的一个很重要的概念,因为类是很多个具有相同属性和行为特征的对象所抽象出来的,对象是类的一个实例。

    然后学java只做一件事:就是不断创建对象,使用对象,指挥对象,管理维护对象之间的关系。

    1.3小结

    面向过程:是一种以过程为中心的编程思想,强调步骤化的思考方式。

    面向对象:管理维护对象之间的关系( 属性 就是该事物的描述信息      行为 就是该事物能够做什么)

    2.类与对象及其使用

    3.成员变量与局部变量区别

    3.1成员变量和局部变量的区别?

    A:在类中的位置不同
      成员变量:在类中方法外
      局部变量:在方法定义中或者方法声明上
    B:在内存中的位置不同
      成员变量:在堆内存
      局部变量:在栈内存
    C:生命周期不同
      成员变量:随着对象的创建而存在,随着对象的消失而消失
      局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
    D:初始化值不同
      成员变量:有默认初始化值
      局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

    注意事项:
      局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

    3.2成员变量与局部变量定义

    定义属性语法格式如下:

      [修饰符] 属性类型  属性名 [=默认值]

    • 成员变量 
      • 实例属性(不以static修饰)
      • 类属性(以static修饰)
    • 局部变量
      • 形参(方法签名中定义的变量)
      • 方法局部变量(在方法内定义)
      • 代码块局部变量(在代码块内定义)
    class Varialbe {
        int num; //0
        public  static int number;//类属性,初始值为0
        public void show(int a ) {//a 局部变量方式1 不用显示初始化
            int num2 = 20;//局部变量方式2
            System.out.println("num2 = "+num2);
            System.out.println("a = "+ a);
        }
        {
            double  d = 20.2;//局部变量方式3
            System.out.println("d = "+ d);
        }
    }
    public class test7 {
        public static void main(String[] args) {
            Varialbe v = new Varialbe();
            System.out.println("成员非static = "+v.num); //访问成员变量
            System.out.println("类调用类属性 = "+Varialbe.number);
            System.out.println("对象调用类属性 ="+v.number);
            v.show(3);
        }
    }

     3.3变量使用规则

    变量什么时候定义为成员变量:
    如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。

    变量到底定义在哪里好呢?
    变量的范围是越小越好。因为能及时的被回收。

    4.匿名对象

    /*
        匿名对象:就是没有名字的对象。
        
        匿名对象的应用场景:
            A:调用方法,仅仅只调用一次的时候。
                注意:调用多次的时候,不适合。
                那么,这种匿名调用有什么好处吗?
                    有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
            B:匿名对象可以作为实际参数传递
    */
    class Student {
        public void show() {
            System.out.println("我爱学习");
        }
    }
    
    class StudentDemo {
        public void method(Student s) {
            s.show();
        }
    }
    
    class NoNameDemo {
        public static void main(String[] args) {
            //带名字的调用
            Student s = new Student();
            s.show();
            s.show();
            System.out.println("--------------");
            
            //匿名对象
            //new Student();
            //匿名对象调用方法
            new Student().show();
            new Student().show(); //这里其实是重新创建了一个新的对象
            System.out.println("--------------");
            
            
            //匿名对象作为实际参数传递
            StudentDemo sd = new StudentDemo();
            //Student ss = new Student();
            //sd.method(ss); //这里的s是一个实际参数
            //匿名对象
            sd.method(new Student());
            
            //在来一个
            new StudentDemo().method(new Student());
         }
    }

    5.封装private

    private:是一个权限修饰符 ,可以修饰成员变量和成员方法 ,被其修饰的成员只能在本类中被访问

    封装概述: 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

    好处: 隐藏实现细节,提供公共的访问方式 提高了代码的复用性 提高安全性。

    封装原则: 将不需要对外提供的内容都隐藏起来。 把属性隐藏,提供公共方法对其访问。

    6.this与super关键字

    6.1分析this与super使用场景

         问题是:
             1.我不仅仅要输出局部范围的变量num,还要输出本类成员范围的变量num。怎么办呢?
             2.我还想要输出父类成员范围的变量num。怎么办呢?
                 如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
                 恭喜你,这个关键字是存在的:super。
                 
         this和super的区别?
             分别是什么呢?
                 this代表本类对应的引用。
                 super代表父类存储空间的标识(可以理解为父类的引用,可以操作父类的成员,但不是父类的对象!)
     
             怎么用呢?
                 A:访问成员变量
                     this.成员变量     调用本类的成员变量
                     super.成员变量    调用父类的成员变量
                 B:访问构造方法(在子父类的构造方法问题讲)
                     this(...)        调用本类的构造方法
                     super(...)       调用父类的构造方法
                 C:访问成员方法(在子父类的成员方法问题讲)
                     this.成员方法     调用本类的成员方法
                     super.成员方法    调用父类的成员方法
    
     class Father {
         public int num = 10;
     }
     
     class Son extends Father {
         public int num = 20;
         
         public void show() {
             int num = 30;
             System.out.println(num);
             System.out.println(this.num);
             System.out.println(super.num);
         }
     }
     
     class ExtendsDemo5 {
         public static void main(String[] args) {
             Son s = new Son();
             s.show();
         }
    }

     6.2this与super 区别及注意事项

      1)super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 

      2)this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
      3)super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名    super.成员函数据名(实参)

      4)this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)

      5)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。

      6)super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。

      7)super()和this()均需放在构造方法内第一行。

      8)尽管可以用this调用一个构造器,但却不能调用两个。

      9)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

      10)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。

      11)从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

    7.构造器

    (1)作用:用于对对象的数据进行初始化
    (2)格式:
    A:构造器名和类名相同
    B:没有返回值类型,也没有返回值,连void都不能有
    C:修饰符可以省略,也可以是 public、protected、private其中之一
    D:形参列表

    思考题(1):构造方法中可不可以有return语句呢?
    可以。而是我们写成这个样子就OK了:return;
    其实,在任何的void类型的方法的最后你都可以写上:return;
    思考题(2):如果为构造器定义了返回值,或使用void定义构造器没有返回值,编译时不会报错,但java会把这个所谓的构造器当成方法来处理。

    (3)构造方法的注意事项
    A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
    B:如果我们给出了构造方法,系统将不再提供默认构造方法
    如果这个时候,我们要使用无参构造方法,就必须自己给出。
    推荐:永远手动自己给出无参构造方法。
    (4)给成员变量赋值的方式
    A:setXxx()
    B:带参构造方法

    8.static关键字

    8.1static的特点:

    A:随着类的加载而加载

    B:优先与对象存在

    C:被类的所有对象共享,这其实也是我们判断该不该使用静态的依据。

    D:可以通过类名调用,既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。

    E:修饰成员变量和成员方法

    8.2静态的内存图

    静态的内容在方法区的静态区


    8.3静态的注意事项

    A:在静态方法中没有this对象

    如何理解呢?
    静态是随着类的加载而加载,this是随着对象的创建而存在。
    静态比对象先存在。

    B:静态方法只能访问静态的成员变量和静态的成员方法
    静态方法:
    成员变量:只能访问静态变量
    成员方法:只能访问静态成员方法
    非静态方法:
    成员变量:可以是静态的,也可以是非静态的
    成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
    简单记:
    静态只能访问静态。

    8.4静态变量和成员变量的区别


    A:所属不同
    静态变量:属于类,类变量
    成员变量:属于对象,对象变量,实例变量
    B:内存位置不同
    静态变量:方法区的静态区
    成员变量:堆内存
    C:生命周期不同
    静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
    成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
    D:调用不同
    静态变量:可以通过对象名调用,也可以通过类名调用
    成员变量:只能通过对象名调用

    8.5 main方法的格式讲解:

    public static void main(String[] args) {...}

    public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。
    static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。
    void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。
    main:是一个常见的方法入口。我见过的语言都是以main作为入口。
    String[] args:这是一个字符串数组。值去哪里了?
    这个东西到底有什么用啊?怎么给值啊?
    这个东西早期是为了接收键盘录入的数据的。
    格式是:
    java MainDemo hello world java

    class MainDemo {
        public static void main(String[] args) {
            //System.out.println(args); //[Ljava.lang.String;@175078b
            //System.out.println(args.length); //0
            //System.out.println(args[0]); //ArrayIndexOutOfBoundsException
            
            //接收数据后
            System.out.println(args); 
            System.out.println(args.length); 
            //System.out.println(args[0]); 
            for(int x=0; x<args.length; x++) {
                System.out.println(args[x]);
            }
        }
    }

    9.代码块

    代码块:在Java中,使用{}括起来的代码被称为代码块。
    根据其位置和声明的不同,可以分为
    局部代码块:局部位置,用于限定变量的生命周期,限定变量生命周期,及早释放,提高内存利用率


    构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
    作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。
    静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
    作用:一般是对类进行初始化。

    面试题?
    静态代码块,构造代码块,构造方法的执行顺序?
    静态代码块 -- 构造代码块 -- 构造方法
    静态代码块:只执行一次
    构造代码块:每次调用构造方法都执行

    /*
        写程序的执行结果。
        
        林青霞都60了,我很伤心
        我是main方法
        Student 静态代码块
        Student 构造代码块
        Student 构造方法
        Student 构造代码块
        Student 构造方法
    */
    class Student {
        static {
            System.out.println("Student 静态代码块");
        }   
        {
            System.out.println("Student 构造代码块");
        }    
        public Student() {
            System.out.println("Student 构造方法");
        }
    }
    class StudentDemo {
        static {
            System.out.println("林青霞都60了,我很伤心");
        }   
        public static void main(String[] args) {
            System.out.println("我是main方法");
            
            Student s1 = new Student();
            Student s2 = new Student();
        }
    }

    9.继承

    9.1继承概述

    继承概述:
    把多个类中相同的内容给提取出来定义到一个类中。

    如何实现继承呢?
    Java提供了关键字:extends

    格式:
    class 子类名 extends 父类名 {}

    好处:
    A:提高了代码的复用性
    B:提高了代码的维护性
    C:让类与类之间产生了关系,是多态的前提

    类与类产生了关系,其实也是继承的一个弊端:
    类的耦合性增强了。

    开发的原则:低耦合,高内聚。
    耦合:类与类的关系
    内聚:就是自己完成某件事情的能力

    9.2继承特点

    A:Java只支持单继承,不支持多继承。
    有些语言是支持多继承,格式:extends 类1,类2,...
    B:Java支持多层继承(继承体系)

    9.3继承注意事项

    继承的注意事项:
    A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
    B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
    C:不要为了部分功能而去继承

    9.4什么时候考虑使用继承呢?

    继承其实体现的是一种关系:"is a"。
    Person
    Student
    Teacher
    水果
    苹果
    香蕉
    橘子

    采用假设法。
    如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

    9.5继承中成员变量的关系?

    继承中成员变量的关系:
    A:子类中的成员变量和父类中的成员变量名称不一样,这个太简单。
    B:子类中的成员变量和父类中的成员变量名称一样,这个怎么玩呢?
    在子类方法中访问一个变量的查找顺序:
    a:在子类方法的局部范围找,有就使用
    b:在子类的成员范围找,有就使用
    c:在父类的成员范围找,有就使用
    d:如果还找不到,就报错。

    9.6 this 与super 区别?

    问题是:
    我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?
    我还想要输出父类成员范围的num。怎么办呢?
    如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
    恭喜你,这个关键字是存在的:super。

    this和super的区别?
    分别是什么呢?
    this代表本类对应的引用。
    super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)

    怎么用呢?
    A:调用成员变量
    this.成员变量 调用本类的成员变量
    super.成员变量 调用父类的成员变量
    B:调用构造方法
    this(...) 调用本类的构造方法
    super(...) 调用父类的构造方法
    C:调用成员方法
    this.成员方法 调用本类的成员方法
    super.成员方法 调用父类的成员方法

    9.7继承中构造方法的关系?

    继承中构造方法的关系
    A:子类中所有的构造方法默认都会访问父类中空参数的构造方法
    B:为什么呢?
    因为子类会继承父类中的数据,可能还会使用父类的数据。
    所以,子类初始化之前,一定要先完成父类数据的初始化。

    注意:子类每一个构造方法的第一条语句默认都是:super();

    如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
    报错。
    如何解决呢?
    A:在父类中加一个无参构造方法
    B:通过使用super关键字去显示的调用父类的带参构造方法
    C:子类通过this去调用本类的其他构造方法
    子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。

    注意事项:
    this(...)或者super(...)必须出现在第一条语句上。
    如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。

    9.8继承中测试题

    测一:

    看程序写结果:
    A:成员变量 就近原则
    B:this和super的问题
    this访问本类的成员
    super访问父类的成员
    C:子类构造方法执行前默认先执行父类的无参构造方法
    D:一个类的初始化过程
    成员变量进行初始化
    默认初始化
    显示初始化
    构造方法初始化

    结果:
    fu
    zi
    30
    20
    10
    class Fu{
        public int num = 10;
        public Fu(){
            System.out.println("fu");
        }
    }
    class Zi extends Fu{
        public int num = 20;
        public Zi(){
            System.out.println("zi");
        }
        public void show(){
            int num = 30;
            System.out.println(num); //30
            System.out.println(this.num); //20
            System.out.println(super.num); //10
        }
    }
    class ExtendsTest {
        public static void main(String[] args) {
            Zi z = new Zi();
            z.show();
        }
    }

    测二:

    看程序写结果:
    A:一个类的静态代码块,构造代码块,构造方法的执行流程
    静态代码块 > 构造代码块 > 构造方法
    B:静态的内容是随着类的加载而加载
    静态代码块的内容会优先执行
    C:子类初始化之前先会进行父类的初始化

    结果是:
    静态代码块Fu
    静态代码块Zi
    构造代码块Fu
    构造方法Fu
    构造代码块Zi
    构造方法Zi

    class
    Fu { static { System.out.println("静态代码块Fu"); } { System.out.println("构造代码块Fu"); } public Fu() { System.out.println("构造方法Fu"); } } class Zi extends Fu { static { System.out.println("静态代码块Zi"); } { System.out.println("构造代码块Zi"); } public Zi() { System.out.println("构造方法Zi"); } } class ExtendsTest2 { public static void main(String[] args) { Zi z = new Zi(); } }

    测三:

    
    

    看程序写结果:
    A:成员变量的问题
    int x = 10; //成员变量是基本类型
    Student s = new Student(); //成员变量是引用类型
    B:一个类的初始化过程
    成员变量的初始化
    默认初始化
    显示初始化
    构造方法初始化
    C:子父类的初始化(分层初始化)
    先进行父类初始化,然后进行子类初始化。

    结果:
    YXYZ

    问题:
    虽然子类中构造方法默认有一个super()
    初始化的时候,不是按照那个顺序进行的。
    而是按照分层初始化进行的。
    它仅仅表示要先初始化父类数据,再初始化子类数据。

    class X {
        Y b = new Y();
        X() {
            System.out.print("X");
        }
    }
    
    class Y {
        Y() {
            System.out.print("Y");
        }
    }
    
    public class Z extends X {
        Y y = new Y();
        Z() {
            //super()
            System.out.print("Z");
        }
        public static void main(String[] args) {
            new Z(); 
        }
    }

    9.9继承中的成员方法的关系:

    继承中成员方法的关系:
    A:子类中的方法和父类中的方法声明不一样,这个太简单。
    B:子类中的方法和父类中的方法声明一样,这个该怎么玩呢?
    通过子类对象调用方法:
    a:先找子类中,看有没有这个方法,有就使用
    b:再看父类中,有没有这个方法,有就使用
    c:如果没有就报错。

    9.10方法重写应用及注意事项:

    方法重写应用?

    
    

    方法重写:子类中出现了和父类中方法声明一模一样的方法。

    方法重载:
    本类中出现的方法名一样,参数列表不同的方法。与返回值无关。

    
    

    子类对象调用方法的时候:
    先找子类本身,再找父类。

    方法重写的应用:
    当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
    这样,即沿袭了父类的功能,又定义了子类特有的内容。

    案例:
    A:定义一个手机类。
    B:通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
    按照我们基本的设计,我们把代码给写出来了。
    但是呢?我们又发现新手机应该是手机,所以,它应该继承自手机。
    其实这个时候的设计,并不是最好的。
    因为手机打电话功能,是手机本身就具备的最基本的功能。
    所以,我的新手机是不用在提供这个功能的。
    但是,这个时候,打电话功能就没有了。这个不好。
    最终,还是加上这个功能。由于它继承了手机类,所以,我们就直接使用父类的功能即可。
    那么,如何使用父类的功能呢?通过super关键字调用



    class
    Phone { public void call(String name) { System.out.println("给"+name+"打电话"); } } class NewPhone extends Phone { public void call(String name) { //System.out.println("给"+name+"打电话"); super.call(name); System.out.println("可以听天气预报了"); } } class ExtendsDemo9 { public static void main(String[] args) { NewPhone np = new NewPhone(); np.call("林青霞"); } }

    方法重写注意事项:

    方法重写的注意事项
    A:父类中私有方法不能被重写
    因为父类私有方法子类根本就无法继承
    B:子类重写父类方法时,访问权限不能更低
    最好就一致
    C:父类静态方法,子类也必须通过静态方法进行重写
    其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解

    子类重写父类方法的时候,最好声明一模一样。

    10.final

    10.1 final 特点:

    final可以修饰类,方法,变量

    final可以修饰类,该类不能被继承。
    final可以修饰方法,该方法不能被重写。(覆盖,复写)
    final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。

    常量:
    A:字面值常量
    "hello",10,true
    B:自定义常量
    final int x = 10;

    10.2 final修饰局部变量问题

    final修饰局部变量的问题
    基本类型:基本类型的值不能发生改变。
    引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

    10.3final 修饰变量初始化时机

    A:被final修饰的变量只能赋值一次。
    B:在构造方法完毕前。(非静态的常量)

    11.多态

    11.1多态概述

    多态:同一个对象(事物),在不同时刻体现出来的不同状态。
    举例:
    猫是猫,猫是动物。
    水(液体,固体,气态)。

    多态的前提:
    A:要有继承关系。
    B:要有方法重写。
    C:要有父类引用指向子类对象。

    11.2多态中的成员访问特点:

    多态中的成员访问特点:
    A:成员变量
    编译看左边,运行看左边。
    B:构造方法
    创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
    C:成员方法
    编译看左边,运行看右边。
    D:静态方法
    编译看左边,运行看左边。
    (静态和类相关,算不上重写,所以,访问还是左边的)

    由于成员方法存在方法重写,所以它运行看右边。

    11.3多态的好处与弊端

    多态的好处:
    A:提高了代码的维护性(继承保证)
    B:提高了代码的扩展性(由多态保证)

    多态的弊端:
    不能使用子类的特有功能。

    我就想使用子类的特有功能?行不行?
    行。
    怎么用呢?
    A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
    B:把父类的引用强制转换为子类的引用。(向下转型)

    对象间的转型问题:
    向上转型:
    Fu f = new Zi();
    向下转型:
    Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

    ClassCastException:类型转换异常
    一般在多态的向下转型中容易出现

    12.抽象类

    12.1抽象类的规则:

    A:抽象类和抽象方法必须用abstract关键字修饰

    B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类

    C:抽象类不能实例化
    因为它不是具体的。
    抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
    用于子类访问父类数据的初始化

    D:抽象的子类
    a:如果不想重写抽象方法,该子类是一个抽象类。
    b:重写所有的抽象方法,这个时候子类是一个具体的类。
    抽象类的实例化其实是靠具体的子类实现的。是多态的方式。

    E:抽象类可以包含(属性,方法,构造器,初始化块,内部类,枚举)

    属性:成员变量 即可以是变量,也可以是常量

    方法:可以是普通方法和抽象方法

    构造器:用于子类访问父类数据的初始化。

    抽象方法: 强制要求子类做的事情。
    非抽象方法: 子类继承的事情,提高代码复用性。

    12.2abstract不能和那些关键字共存?

    private 冲突   abstract修饰的方法必须被其子类重写才有意义,否则这个方法将永远不会有方法体
    final 冲突  final修饰的类不能被继承,final修饰的方法不能被重写,因此final与abstract永远不能同时使用
    static 无意义 static修饰属于类级别的 ,即没有所谓的类抽象方法

    13.接口

    13.1接口的定义

    [修饰符]  interface 接口名 extends 父接口1,父接口2,,,{

      常量

      抽象方法

      内部类(内部接口)

      枚举

    }

    ①修饰符   public/省略,如果省略了public,则默认采用包权访问控制符,即只有在相同包结构下才能可以访问该接口。

    ②接口里没有构造器和初始化块

    ③定义接口成员时,可以省略访问修饰符,如果指定修饰符,只能是public。

    ④成员变量 ,只能是常量,并且是静态的,默认修饰符:public static final

    ⑤只能是抽象方法,默认修饰符:public abstract

    ⑥定义内部类或者枚举类 ,默认修饰符:public static

    ⑦ 一个java源文件里可有多个没有修饰符的接口,但只能有一个public接口,并且文件名和接口名一致。

    13.2 类与类 类与接口  接口与接口关系

    类与类:
    继承关系,只能单继承,可以多层继承。
    类与接口:
    实现关系,可以单实现,也可以多实现。
    并且还可以在继承一个类的同时实现多个接口。
    接口与接口:
    继承关系,可以单继承,也可以多继承。

    13.3接口不能实例化的描述问题?

    A:接口不能实例化
    那么,接口如何实例化呢?
    按照多态的方式来实例化。
    B:接口的子类
    a:可以是抽象类。但是意义不大。
    b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

    14.形式参数和返回值的问题深入研究

    形式参数:

    基本类型(太简单,不是我今天要讲解的)
    引用类型:
    类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
    抽象类:需要的是该抽象的类子类对象
    接口:需要的是该接口的实现类对象

    返回值类型:

    基本类型:(基本类型太简单,我不准备讲解)
    引用类型:
    类:返回的是该类的对象
    抽象类:返回的是该抽象类的子类对象
    接口:返回的是该接口的实现类的对象

    15.package 、import 关键字概述及作用

    15.1包的定义

    包的定义
    package 包名;
    多级包用.分开即可

    注意事项:
    A:package语句必须是程序的第一条可执行的代码
    B:package语句在一个java文件中只能有一个
    C:如果没有package,默认表示无包名

    包:
    A:其实就是文件夹
    B:作用
    a:把相同的类名放到不同的包中
    b:对类进行分类管理

    15.2带包的编译和运行

    带包的编译和运行:
    A:手动式
    a:编写一个带包的java文件。
    b:通过javac命令编译该java文件。
    c:手动创建包名。
    d:把b步骤的class文件放到c步骤的最底层包
    e:回到和包根目录在同一目录的地方,然后运行
    带包运行。

    B:自动式
    a:编写一个带包的java文件。
    b:javac编译的时候带上-d即可
    javac -d . HelloWorld.java
    c:回到和包根目录在同一目录的地方,然后运行
    带包运行。

    15.3导包 import

    导包:
    格式:import 包名;
    这种方式导入是到类的名称。
    注意:我们用谁就导谁。

    面试题:
    package,import,class有没有顺序关系?
    有。
    package > import > class

    Package:只能有一个
    import:可以有多个
    class:可以有多个,以后建议是一个

    15.内部类

    15.1内部类的概述及作用:

    内部类概述: 定义在其他类的内部的类就称为内部类。
    内部类作用:①内部类提供了更好的封装,把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

          ②内部类成员可以直接访问外部类的私有数据,但外部类不能直接访问内部类的实现细节。

          ③外部类要访问内部类的成员,必须创建对象。

          ④匿名内部类适合用于创建那些仅需要一次使用的类。

          ⑤内部类修饰符 public 、protected、默认修饰符、private

          

     内部类里面的成员:

    普通初始化块 

    15.2内部类的位置

    内部类位置
    成员位置:在成员位置定义的类,被称为成员内部类。
    局部位置:在局部位置定义的类,被称为局部内部类。(方法内定义内部类)

    成员内部类:
    如何直接访问内部类的成员。
    外部类名.内部类名 对象名 = 外部类对象.内部类对象;

    15.3外部类 内部类 内部类方法的局部变量 同名访问?

    外部类变量:外部类类名.this.属性

    内部类变量:this.属性

    内部类里方法局部变量 :直接访问

    java 不允许在非静态内部类里定义静态成员(静态方法、静态属性、静态初始化块)

    15.4静态内部类

    ①修饰符:static修饰内部类,但static不可修饰外部类

    ②成员:静态成员、非静态成员

    ③访问外部类: 静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

     

    15.5局部内部类

    
    

    局部内部类
    A:可以直接访问外部类的成员
    B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

    面试题:
    局部内部类访问局部变量的注意事项?
    A:局部内部类访问局部变量必须用final修饰
    B:为什么呢?
    局部变量是随着方法的调用而调用,随着调用完毕而消失。
    而堆内存的内容并不会立即消失。所以,我们加final修饰。
    加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
    我在内存中存储的是数据20,所以,我还是有数据在使用。



    class
    Outer { private int num = 10; public void method() { //int num2 = 20; //final int num2 = 20; class Inner { public void show() { System.out.println(num); //从内部类中访问本地变量num2; 需要被声明为最终类型 System.out.println(num2);//20 } } //System.out.println(num2); Inner i = new Inner(); i.show(); } } class InnerClassDemo5 { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }

    15.6匿名内部类 

    
    

    匿名内部类
    就是内部类的简化写法。

    
    

    前提:存在一个类或者接口
    这里的类可以是具体类也可以是抽象类。

    格式:
    new 类名或者接口名(){
    重写方法;
    }

    本质是什么呢?
    是一个继承了该类或者实现了该接口的子类匿名对象。


    interface
    Inter { public abstract void show(); public abstract void show2(); } class Outer { public void method() { //一个方法的时候 new Inter() { public void show() { System.out.println("show"); } }.show(); } } class InnerClassDemo6 { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }

    15.7匿名内部类多个方法调用方式

    interface Inter {
        public abstract void show();
        public abstract void show2();
    }
    
    class Outer {
        public void method() {
    
            //二个方法的时候
            /*
            new Inter() {
                public void show() {
                    System.out.println("show");
                }
                
                public void show2() {
                    System.out.println("show2");
                }
            }.show();
            
            new Inter() {
                public void show() {
                    System.out.println("show");
                }
                
                public void show2() {
                    System.out.println("show2");
                }
            }.show2();
            */
            
            //如果我是很多个方法,就很麻烦了
            //那么,我们有没有改进的方案呢?
            Inter i = new Inter() { //多态
                public void show() {
                    System.out.println("show");
                }
                
                public void show2() {
                    System.out.println("show2");
                }
            };
            
            i.show();
            i.show2();
        }
    }
    
    class InnerClassDemo6 {
        public static void main(String[] args) {
            Outer o = new Outer();
            o.method();
        }
    }
    匿名内部类在开发中的使用
    interface
    Person { public abstract void study(); } class PersonDemo { //接口名作为形式参数 //其实这里需要的不是接口,而是该接口的实现类的对象 public void method(Person p) { p.study(); } } //实现类 class Student implements Person { public void study() { System.out.println("好好学习,天天向上"); } } class InnerClassTest2 { public static void main(String[] args) { //测试 PersonDemo pd = new PersonDemo(); Person p = new Student(); pd.method(p); System.out.println("--------------------"); //匿名内部类在开发中的使用 //匿名内部类的本质是继承类或者实现了接口的子类匿名对象 pd.method(new Person(){ public void study() { System.out.println("好好学习,天天向上"); } }); } }

    15.8匿名内部类面试题

    
    

    匿名内部类面试题:
    按照要求,补齐代码
    interface Inter { void show(); }
    class Outer { //补齐代码 }
    class OuterDemo {
    public static void main(String[] args) {
    Outer.method().show();
    }
    }
    要求在控制台输出”HelloWorld”


    interface
    Inter { void show(); //public abstract } class Outer { //补齐代码 public static Inter method() { //子类对象 -- 子类匿名对象 return new Inter() { public void show() { System.out.println("HelloWorld"); } }; } } class OuterDemo { public static void main(String[] args) { Outer.method().show(); /* 1:Outer.method()可以看出method()应该是Outer中的一个静态方法。 2:Outer.method().show()可以看出method()方法的返回值是一个对象。 又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。 */ } }
  • 相关阅读:
    Redis 简介
    图片懒加载、selenium和PhantomJS
    Python网络爬虫之三种数据解析方式
    Scrapy框架之CrawlSpider
    Scrapy 框架
    python 网络爬虫概念与HTTP(s)协议
    Mysql概念及基本操作
    Python re 模块
    线程与进程应用场景
    全局解释器锁 GIL
  • 原文地址:https://www.cnblogs.com/not-miss/p/11220108.html
Copyright © 2020-2023  润新知