Java学习之路(四):面向对象

Java中的面向对象

概念:面向对象的原本的意思是“”万物皆对象“”

面向对象思想的特点:

  • 是一种更符合我们思想习惯的思想,将复杂的事情简单化
  • 使我们角色发生了转换,将我们从执行者变成了指挥者

面向对象的特征:

  • 封装(Encapsulation)
  • 继承(Inheritance)
  • 多态(Polymorphism)

一些专业性的词汇:

  • 面向对象的分析(OOA,Object Oriented Analysis)
  • 面向对象的设计(OOD,Object Oriented Design)
  • 面向对象的编程实现(OOP,Object Oriented Programming)

面向对象的开发或者说面向对象的编程的本质就是不断的创建对象,使用对象,指挥对象做事情,管理和维护对象之间的关系


 面向对象的基本概念

  对象就是指人们要进行研究的世界上的任何事物,从最简单的整数到复杂的飞机...均都可以看做是一个对象,它不仅仅能表示具体的事物,还能抽象的规则、计划或事件

如何描述现实世界的事物

  • 属性:就是该事物的描述信息(事物身上的名词)
  • 行为:就是该事物能够做什么(事物身上的动词)

Java中最基本的单位是类,Java中是用class来描述一件事物

  • 类中有成员变量,就是事物的属性

  • 类中有成员方法,就是事物的行为

其实我们学习java是学些什么?就是学习面向对象
    声明类
    声明成员变量
    声明成员方法
    创建对象
    给属性赋值
    使用对象

类和对象的概念

  • 类:是一组相关的属性和行为的集合
  • 对象:是该类事物的具体体现
  • 注意:其实一个class类实例化后就是一个对象了

类、属相和方法的声明

  • 类的声明:class关键字,eg:class Student
  • 属性的声明:数据类型  属性名,eg:String  name
  • 方法的声明:public  返回值类型  方法名(){ }
//声明一个学生类
//属性:姓名,年龄,性别
//行为:学习,睡觉

class Student{
    String name;
    int age;
    boolean sex;
    public void study(){
        System.out.println("这里是学习方法")
    }
    public void sleep(){
        System.out.println("这里是睡觉方法")
    }
}

类的使用

  • 创建对象:类名  对象名 = new 类名();
  • 给属性赋值:对象名.变量名
  • 调用方法:对象名.方法名()

Java中的垃圾回收机制

Java会自动回收无用的对象占用的内存空间,使该空间可以被程序再次使用,程序员不需要向C语言一样要自己进行释放内存的空间,CFRelease()

成员变量和局部变量之间的区别

  • 在类中的位置不同
    • 成员变量:在类之中,方法之外
    • 局部变量:实在方法中定义的
  • 在内存中的位置不同
    • 成员变量:在堆内存(成员变量属于对象,对象进堆内存)
    • 局部变量:位于栈内存(局部变量属于方法,方法进入栈内存)
  • 声明周期不同
    • 成员变量:随着对象的创建而存在,随着对象的消失而消失
    • 局部变量:对着方法的调用而存在,随着方法的调用完毕而消失
  • 初始化的值不同
    • 成员变量:有默认的初始化值
    • 局部变量:没有默认的初始化值,必须定义,赋值然后才能使用

成员变量和局部变量的注意事项:

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

基本数据类型(传值)和引用数据类型(传地址)有哪些?

1.基本数据类型:byte,short,int,long,float,double,boolean,char

2.引用数据类型:数组(eg:int[]),类(class),接口(interface),枚举

方法的形式参数是一个类名的适合如何调用?

  如果你看到一个方法形式参数是一个类类型(引用类型)的话,那么调用方法的时候其实需要的是该类的对象。

匿名对象

什么是匿名对象:没有给新创建的对象储存在一个变量里

应用的场景:

  1.调用方法,仅仅只需要调用一次的时候、

  2.匿名对象可以作为实际的参数进行传递


封装概述:

  是指隐藏对象的属性和实现细节,仅仅对外提供公用的public访问方式

封装好处:

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

封装原则:

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

Private(私有)关键字

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

当成员变量用private修饰表示外界不能访问

this关键字的特点

  • 代表当前对象的引用

this的应用场景

  • 用来区分成员变量和局部变量的重名

this是和外面调用的变量指向同一个地址的,指的是同一对象。

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

像这样,再构造方法中的应用就是最好的例子。

如果你不加this,你可以试一下,会有很好玩的事情发生。

构造方法Constructor的概述

构造方法的作用:给对象的数据(属性)进行初始化的一个赋值

构造方法的特点:

  • 方法名与类名相同(大小也与类名一致)
  • 没有返回值类型,注意:void也不要写,什么都不写
  • 没有具体的返回值return 

构造方法分为

  • 有参构造方法
  • 无参构造方法

构造方法的重载:

  是指方法名相同,与返回值类型无关(构造方法没有返回值),只看参数列表

构造方法的注意事项

  • 如果我们没有给出构造方法,那么系统会默认给出一个无参数的构造方法
  • 如果我们给出了构造方法,系统将不在提供默认的无参构造方法
  • 如果我们声明的有参构造方法,这个时候。如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法。
  • 正确的构造方法的格式【public 类名()】

static关键字

static关键字的特点:

  • 随着类的加载而加载
  • static修饰的东西是优先于对象的存在
  • 被类的所有对象共享

共性用静态,特性用非静态

static声明的成员属性可以通过类名进行调用

  • 其实其本身也可以通过实例化的对象进行调用
  • 推荐使用类名进行调用
  • 静态修饰的内容我们一般称之为:与类相关的类成员

注意事项:

  • static可以用来修饰属性,也可以用来修饰方法
  • 在静态方法中是没有this关键字的
    • 静态是随着类的加载而加载的,this则是随着对象的创建而进行创建的
    • 静态比对象要优先
  • 静态方法只能访问静态的成员变量和静态的成员方法
  • 非静态的方法可以访问静态的成员变量和静态的成员方法
静态变量和成员变量的区别

1.静态变量又叫类变量,成员变量又叫对象变量
2.所属不同:
    静态变量属于类()
    成员变量属于对象,所以也称之为实例变量(对象变量)
3.内存中的位置不同
    静态变量属于类,在方法区的静态区
    成员变量存储与堆内存
4.内存出现时间不同
    静态变量随着类的加载而加载,随着类的消失而消失
    成员变量随着对象的创建而存在,随着对象的消失而消失
5.调用不同
    静态变量可以通过类名调用,也可以通过对象调用
    成员变量只能通过对象调用

代码块的概述:使用{}括起来的代码就称之为代码块

代码块的分类:

根据其位置和声明的不同,可以分为:

  • 局部代码块
  • 构造代码块
  • 静态代码块
  • 同步代码块(多线程)

局部代码块:在方法中出现,限定变量的生命周期,及早释放,提高内存的利用率

构造代码块:在类中方法外出现,多个构造方法中相同代码存放到一起,每次调用构造都执行,并且在构造方法前执行(注意了,构造代码块和构造方法可不是同一种东西)

静态代码块(最常用):在类中方法外出现,并且要加上static修饰,用于给类进行初始化,在加载的时候就执行,并且只执行一次,一般用于加载驱动

//局部代码块
public class null01 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        {
            int a = 1;
            System.out.println(a);
        }//代码块执行结束,变量a被释放
    }

}
//构造代码块
class
Student{ String name; int age; public Student(){ name = "null"; age = 20; } { System.out.println("这就是构造代码块"); } } //每次都会执行,而且是优先于构造方法执行的
//静态代码块
class Student{
    String name;
    int age;
    public Student(){
        name = "null";
        age = 20;
    }
    {
        System.out.println("这就是构造代码块");
    }
    static{
        System.out.println("这里是静态代码块");
    }//在加载的时候就会执行,而且只会执行这一次。一般用于加载驱动
}

继承概述:让类与类之间产生关系,子父关系

继承的好处:

  • 提高代码的复用性
  • 提高代码的维护性
  • 让类与类之间产生了关系,继承是多态的前提

继承的弊端:

  • 类的耦合性增强了
  • 开发的原则:高内聚(自己完成某事),低耦合

继承的特点:

  • Java只支持单继承,不支持多继承(关键字 extends)
  • Java支持多层继承
    • 如果想用这个体系的所有功能,我们有最底层的类来创建对象
    • 如果想用这个体系的共性功能,我们调用最顶层的类

继承的注意事项:

  • 子类只能继承父类所有的非私有的成员(非私有的成语方法和成员变量)
  • 子类可以通过super关键字访问父类的东西

super和this

  • super的作用:super指的是当前类的对象的父类引用
  • super可以调用父类的成员属性  super.成员变量
  • super可以调用父类的成员方法  super.成员方法
  • super可以调用父类的构造方法  super(...)
  • .
  • this的作用:this指的是当前类的对象引用
  • this可以调用本类的成员属性
  • this可以调用本类的成员方法
  • this可以调用父类的成员方法(在本类没有的情况下)  this.父类方法、this.父类属性
  • this可以调用本类的构造方法

继承中的构造方法的关系

子类中的所有的构造方法默认都会访问父类中空参数的构造方法

  应为子类会继承父类中的数据,可能还会使用父类的数据,所以在子类的初始化之前,一定要用super首先要完成父类的初始化

  所以我们会发现,当我们利用Eclipse工具生成子类的构造方法时就会存在super()方法

继承工构造方法的注意事项

  • 子类必须创建无参构造方法,内还要调用父类的构造方法
  • 子类实现有参构造方法
  • 父类自己实现无参构造方法
  • super()和this都是必须出现在构造方法的第一条语句上

方法的重写

指的是子类中出现和父类一模一样的方法。重写这个概念只存在与继承的父子之间

应用场景:

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

注意事项:

  父类中私有方法不能重写,因为父类私有方法子类根本就无法继承

  子类重写父类的时候,访问权限最好一致

方法的重写与重载

Overload是指方法的重载,重载可以改变返回值类型,方法的重载只看参数类表不同

Override是指方法的重写,也就是子类中出现了和父类中方法声明一模一样的方法

方法的重写与返回值类型有关,返回值是一致的(或者是子父类)的

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

Final关键字修饰类,方法以及变量

final修饰的特点:

  • 修饰类,类不能被继承
  • 修饰变量,变量就变成了常量,只能被赋值一次
  • 修饰方法,方法就不能被重写

修饰变量:

  • final修饰变量叫常量,一般会与public static公用
  • 注:常量的变量名一定要全部大写

final修饰局部变量:

  • 修饰基本类型,值不能被改变
  • 修饰引用类型,是地址不能被改变,对象中的属性可以改变
  • 修饰引用类型,那就不可以在new对象了

多态的概述 

什么是多态:事物的多种状态...

Java中存在多态的前提条件:

  • 要有继承关系
  • 要有方法的重写
  • 要有父类引用指向子类对象(Father son = new Son())

多态中的成员访问特点:

  • 成员变量:编译看左边(父类),运行看左边(父类)
  • 成员方法:编译看左边(父类),运行看右边(子类)
  • 静态方法:编译看左边(父类),运行看左边(父类)
  • 总结:只有非静态的成员方法,编译看左边,运行看右边

注意:在多态的写法中,父类指向了子类,我们实例化然后调用一个方法是,这个方法在父类中必须存在,否则将会无法进行编译

多态中的向上转型和向下转型

  • 向上转型:父类指向子类对象 Father p = new Son();
  • 向下转型:子类指向父类对象 Son son = (Son)p;

  向下转型注意:父类的真实对象必须是子类对象,否则会有问题

多态的好处与弊端:

  • 提高了代码的维护性
  • 提高了代码的扩展性
  • 但是却不能使用子类的特有属性和行为

抽象类的特点:

  • 抽象类和抽象方法必须用abstract关键字修饰
    • abstract class 类名{}
    • public abstract void eat();
  • 抽象类不一定有抽象方法,有抽象方法的类一定是个抽象类或者是接口
  • 抽象类不能实例化,要由具体的子类实例化。这也是多态的一种(抽象类多态)
  • 抽象类的子类:要么是抽象类,要么重写抽象类中所有的抽象方法

抽象类的成员的特点:

  • 成员变量:既可以是变量,也可以是常量。
  • abstract不能修饰成员变量,只能修饰类和方法
  • 构造方法:抽象类也是有构造方法的,用于子类访问父类数据的初始化
  • 成员方法:抽象类的方法可以是抽象的,也可以是非抽象的

抽象类的成员的特性:

  • 抽象方法:强制要求子类实现
  • 非抽象方法:子类可以继承实现

接口

  • 从狭义的角度上将,就是指java中的interface关键字
  • 从广义上讲对外提供规则的都是接口
  • 接口就是提供对外访问的规则

接口的特点:

  • 接口用关键字interface表示   interface 接口名{}
  • 类去实现接口用implements表示  class 类名  implements  接口名{}
  • 接口不能进行实例化
  • 接口的子类可以是抽象类(没有意义),一个具体的类,要重写接口中的所有方法

类与类,类与接口,接口与接口的关系

类与类:

  继承关系,只能是单继承,可以多层继承

类与接口:

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

接口与接口:

  继承关系,可以单继承,也可以多继承

抽象类与接口的区别

1.成员区别

  • 抽象类可以有成员变量,也可以有常量,构造方法,成员方法(抽象的和非抽象的)
  • 接口只能有变量,方法只能是抽象方法

2.关系区别

  • 类与类:继承关系,单继承
  • 类与接口:实现关系,单实现和多实现均可
  • 接口与接口:继承关系,单继承与多继承

3.设计理念的区别

  • 抽象类:抽象类中定义的是该继承体系的共性功能
  • 接口:接口中定义的是该继承体系的扩展功能

package关键字的概述以及作用

package包的作用:

  • 包其实就是文件夹
  • 包的作用是将字节码(.class)进行分类存放
  • 包的作用可以使在同一个项目中有相同的类
  • 包的作用有利于以后功能模块的划分

包的格式的定义:

  • 包名一般使用公司域名的倒写

包的类能被其他的包访问,那么这个包一定是public的类,public修饰的类代表其他包可以访问此类

四中权限修饰符:
  private,default,protected,public

  所谓的权限就是别人是否能访问类、属性、方法

用在类上的修饰符:default,public,final(状态修饰符),abstract(抽象修饰符)

用在成员上的修饰符:权限修饰符(private,default,protected,public),状态修饰符(static,final)

用在构造方法上的修饰符:权限修饰符(private,default,protected,public)

用在成员方法上的修饰符:权限修饰符(private,default,protected,public),状态修饰符(static,final),抽象修饰符(abstract)

protected关键字

表示受保护的

protected修饰的方法只能在当前包中访问,或者由子类访问

 内部类

内部类的概述和访问特点

  • 内部类的概述:就是在class类的内部再定义一个class类
  • 内部类的访问特点:
    • 内部类可以直接访问外部类的成员,包括私有的
    • 外部类要访问内部类的成员,必须要去创建对象

内部类的创建语法:

  外部类名.内部类名 对象名 = 外部类对象.内部类对象;

  注:开发中自己声明的内部类比较少用,用的较多的是集合中的遍历

public class null01内部类 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //创建内部类的对象
        Outer.Inner inner = new Outer().new Inner();
        inner.test1();
    }

    //在一个类的内部声明类,所以他是一个内部类
//    class Student{
        
//    }
    
}
//此时声明类在另一个类的外面,所以这是一个外部类
//class Student{
    
//}
//这是一个外部类
class Outer{
    int a = 12;
    private int b = 13;
    //这是一个内部类
    class Inner{
        public void test1(){
            System.out.println("内部访问外部的一个变量a:"+a);
            System.out.println("内部访问外部的私有属性b:"+b);
            
        }
    }
}
Java内部类的基本用法

1.私有内部类的使用

注:private修饰的,只能在内部访问,所以就无法使用外部类名.内部类名了

那我们如何使用?

和我们对私有属性的操作类似,在class类的内部声明一个获取方法

public class null02私有内部类 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //权限修饰符:private default protected public
        //类的成员:属性,方法,内部类
        
        //创建内部类对象
        //注:private只能在内部访问,所以无法使用Outer.Inner
        //私有的内部类,就不能在外部调用了
        Insert outer = new Insert();
        outer.test();
    }

}
class Insert{
    int a = 12;
    private int b = 13;
    //这是一个内部类
    private class Inner{
        public void test1(){
            System.out.println("内部访问外部的一个变量a:"+a);
            System.out.println("内部访问外部的私有属性b:"+b);
            
        } 
    }
    public void test(){
        Inner inner = new Inner();
        inner.test1();
    }
}
私有内部类的实例

2.静态内部类的使用

创建静态内部方法对象的语句:

  注意:说道对象,那就是new出来的东西了,这个才叫对象

  外部类名.内部类名 对象名 = 外部类名.内部类对象;

public class null03静态内部类 {
    public static void main(String[] args){
        
        //创建静态内部方法对象语法:外部类名.内部类名  对象名 = 外部类名.内部类对象;
        OuterThree.Inner inner = new OuterThree.Inner();
        inner.test1();
        
        
    }
}
class OuterThree{
    static int a = 12;
    static int b = 13;
    //这是一个内部类
    static class Inner{
        public void test1(){
            System.out.println("内部访问外部的一个变量a:"+a);
            System.out.println("内部访问外部的私有属性b:"+b);
            
        } 
    }
}
Java静态内部类

3.调用静态内部类的静态方法

静态内部类的静态方法调用:

  外部类.静态内部类,静态内部方法;

public class null04调用静态类的静态方法 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        
        //调用静态内部类的静态方法
        OuterFour.Inner.test1();
    }

}

class OuterFour{
    static int  a = 1;
    
    //静态的内部类
    static class Inner{
        public static void test1(){
            System.out.println("这里是静态类的静态方法");
            
        }
    }
    
}
静态内部类的静态方法

4.局部内部类

  • 局部内部类如果想要访问局部变量,那么局部变量必须用final修饰
    • 如果不用final修饰,在某些情况下,可能变量会先弹出,但是局部内部类还在存活
  • 局部内部类访问它所在的方法中的局部变量必须用final修饰
  • 注意:jdk1.8以上的版本不需要加final代码也不会报错了
public class Demo01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.test1();
    }
}

class Outer{
    public void test1(){
        final int a = 10;//局部变量
        class Inner{//局部内部类
            public void test2(){
                System.out.println(a);
            }
        }
        Inner inner = new Inner();
        inner.test2();
    }
}
局部内部类

5.匿名内部类

  • 抽象的或者接口的匿名内部类
    • 匿名内部类就是内部类的简化方法
    • 写匿名内部类的前提是存在一个抽象内部类或者是接口
    • 匿名内部类的实现格式:  new 抽象或者是接口名(){重写方法};
    • 匿名内部类的本质:是一个继承了该类或者实现了该接口的子类的匿名对象
    • 匿名内部类的特点:匿名内部类必须实现接口的所有方法;匿名内部类必须实现抽象类的所有方法
    • 匿名内部类的方法调用:就像是普通的对象一样,调用方法即可
public class null05匿名内部类 {
    public static void main(String[] args){
    
        //不能直接调用抽象类
        //可以通过子类去重写抽象类
        Dog dog = new Dog();
        dog.eat();
        //可以通过匿名内部类,其实也是匿名方法
        new Animal(){
            @Override
            public void eat(){
                System.out.println("这个是匿名内部方法");
            }
        }.eat();
        
    }
    
    
}

//写一个抽象类
abstract class Animal{
    public abstract void eat();
}
class Dog extends Animal{
    @Override
    public void eat(){
        System.out.println("我是.....");
    }
}
抽象类的匿名内部类调用
public class null06接口的匿名内部类 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //第一中class实现接口的调用
        DogSix dog = new DogSix();
        dog.jumpFileCircle();
    
        new AnimalSix(){
            @Override
            public void jumpFileCircle() {
                // TODO Auto-generated method stub
                System.out.println("annother Jump....");
            }
        }.jumpFileCircle();
        AnimalSix annther = new AnimalSix(){
            @Override
            public void jumpFileCircle(){
                System.out.println("three jump....");
            }
        };
        annther.jumpFileCircle();
    
    
    }

}

interface AnimalSix{
    //跳火圈
    public void jumpFileCircle();
}
//之前说接口不能直接new,
//如何使用接口、
//1.写一个类,实现接口
class DogSix implements AnimalSix{
    @Override
    public void jumpFileCircle(){
        System.out.println("jump...");
    }
}
//2.new一个接口的匿名
接口的匿名内部类的调用

补充一道面试题:

package nullnull;

interface Inter
{
    void show();
}
class Outer{
    //补齐代码
}
class OutDemo{
    public static void main(String[] args){
        Outer.method().show();
    }
}
//在控制台输出“Helloworld”
interface Inter
{
    void show();
}
class Outer{
    //补齐代码
    public static Inter method(){
        return  new Inter(){
            @Override
            public void show(){
                System.out.println("Helloworld");
            }
        };
    }
}
class OutDemo{
    public static void main(String[] args){
        Outer.method().show();
    }
}
面试题答案

 

posted @ 2018-07-12 17:58  "%201  阅读(238)  评论(0编辑  收藏  举报