java面向对象

来源:互联网 发布:gta5 n卡优化 编辑:程序博客网 时间:2024/06/05 01:52
面向对象的思想概述
l
程序员从执行者转化成了指挥者。
l完成需求时:
Ø先去找具有所需功能的对象来用。
Ø如果该对象不存在,那么创建一个具有所需功能的对象。
Ø这样简化开发并提高复用。
l(class)对象(object)是面向对象的核心概念。
Ø类是对一类事物描述,是抽象的、概念上的定义
Ø对象是实际存在的该类事物的每个个体,因而也称实例(instance)


对象在内存中的图解:


成员变量跟局部变量的两个主要的区别:
1.声明的位置的不同 :成员变量:声明在类里,方法外
 *                           局部变量:声明在方法内,方法的形参部分,代码块内
2 初始化值:成员变量:如果在声明的时候,不显式的赋值,那么不同数据类型会有不同的默认初始化值。
局部变量:一定要显式的赋值。(局部变量没有默认初始化值)
3 二者在内存中存放的位置不同:成员变量存在于堆空间中;局部变量:栈空间中。

对数组操作的几个方法:
    // 数组的反转
    public int[] reverse(int[] arr) {
        for (int x = 0, y = arr.length - 1; x < y; x++, y--) {
            int temp = arr[x];
            arr[x] = arr[y];
            arr[y] = temp;
        }

        return arr;
    }
// 对数组进行排序
    public void sort(int[] arr, String desc) {
        if (desc == "asc") {// ascend:从小到大
            for (int i = 0; i < arr.length - 1; i++) {
                for (int j = 0; j < arr.length - 1 - i; j++) {
                    if (arr[j] > arr[j + 1]) {
                        swap(arr,j,j+1);
                        //swap(arr[j],arr[j + 1]);
                    }
                }
            }
        } else if (desc == "desc") {// 从大到小
            for (int i = 0; i < arr.length - 1; i++) {
                for (int j = 0; j < arr.length - 1 - i; j++) {
                    if (arr[j] < arr[j + 1]) {
                        swap(arr,j,j+1);
                        //swap(arr[j],arr[j + 1]);
                    }
                }
            }
        } else {
            System.out.println("您输入的排序方式有误!");
        }
    }


* 方法的重载(overload)
 * 要求:1.同一个类中 2.方法名必须相同 3.方法的参数列表不同(①参数的个数不同②参数类型不同)
 * 补充:方法的重载与方法的返回值类型没有关系!

对于方法的可变参数

/*
 * 可变个数的形参的方法:
 * 1.格式:对于方法的形参: 数据类型 ... 形参名
 * 2.可变个数的形参的方法与同名的方法之间构成重载
 * 3.可变个数的形参在调用时,个数从0开始,到无穷多个都可以。
 * 4.使用可变多个形参的方法与方法的形参使用数组是一致的。(两个不可以同时存在)
    public void sayHello(String ... args){
        for(int i = 0;i < args.length;i++){
            System.out.println(args[i] + "$");
        }
        //System.out.println("=====");
    }
public void sayHello(String[] args){
        for(int i = 0;i < args.length;i++){
            System.out.println(args[i]);
        }
    }
上述情况,会报错。
用可变参数调用时,可以t.sayHello(new String[]{"hello China","hello BeiJing"});
      也可以  t.sayHello("hello China","hello BeiJing");

 * 5.若方法中存在可变个数的形参,那么一定要声明在方法形参的最后(可变参数形参只能声明在方法参数的最后)
 * 6.在一个方法中,最多声明一个可变个数的形参。

java方法中的参数传递

 * 方法的参数传递(重点、难点)
 * 1.形参:方法声明时,方法小括号内的参数
 *   实参:调用方法时,实际传入的参数的值
 *   
 * 2.规则:java中的参数传递机制:值传递机制
 *   1)形参是基本数据类型的:将实参的值传递给形参的基本数据类型的变量
 *   2)形参是引用数据类型的:将实参的引用类型变量的值(对应的堆空间的对象实体的首地址值)传递给形参的引用类型变量。

面向对象的特征一:封装与隐藏
 * 问题:当创建了类的对象以后,如果直接通过"对象.属性"的方式对相应的对象属性赋值的话,可能会出现不满足实际
 * 情况的意外,我们考虑不让对象来直接作用属性,而是通过"对象.方法"的形式,来控制对象对属性的访问。实际
 * 情况中,对属性的要求就可以通过方法来体现。
 *
 * 解决的方法:(封装性的思想)①将类的属性私有化,②提供公共的方法(setter & getter)来实现调用。
 *
 * 二、权限修饰符:public  private  缺省  protected
 *     可以用来修饰属性、方法
 *     注:1)权限从大到小排列:public protected 缺省 private
 *        2)修饰类的权限有:public 缺省

用来限定该类对象对该类成员(成员变量,方法等)的访问权限。

* 一、类的第三个成员:构造器(constructor 构造方法)
 * constructor:建造者
 * 构造器的作用:①创建对象 ②给创建的对象的属性赋值
 *
 * 1.设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器
 * 2.一旦显式的定义类的构造器,那么默认的构造器就不再提供。
 * 3.如何声明类的构造器。格式:权限修饰符  类名(形参){ }
 * 4.类的多个构造器之间构成重载
 *
 *
 * 二、类对象的属性赋值的先后顺序:①属性的默认初始化 ②属性的显式初始化③通过构造器给属性初始化
 *                           ④通过"对象.方法"的方式给属性赋值

this关键字

 * 1.可以用来修饰属性、方法、构造器
 * 2.this理解为当前对象或当前正在创建的对象.比如:this.name,this.show();(在构造器中使用this表示当前正在创建的对象)
 *
 * 3.可以在构造器中通过“this(形参)”的方式显示的调用本类中其它重载的指定的构造器。
 *   要求:1.在构造器内部必须声明在首行!

 * 一、面向对象的特征二:继承性
 * 1.为什么要设计继承性?
 *
 * 2.通过"class A extends B"类实现类的继承。
 *   子类:A  父类(或基类 SuperClass):B
 *   
 * 3.子类继承父类以后,父类中声明的属性、方法,子类就可以获取到。
 *    明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接
 *        调用罢了。
 *   子类除了通过继承,获取父类的结构之外,还可以定义自己的特有的成分。
 *   
 *   extends:子类是对父类功能的“扩展”,明确子类不是父类的子集。
 *   
 * 4.java中类的继承性只支持单继承:一个类只能继承一个父类。反之,一个父类可以有多个子类。

* 二、方法的重写   ---(方法的重载)     修饰符  返回值类型 方法名 (参数列表){}
 * 1.前提:有子类继承父类
 * 2.子类继承父类以后,若父类的方法对子类不适用,那么子类可以对父类的方法重写(override overwrite)、覆盖、覆写。
 * 3.重写的规则:  1)要求子类方法的“返回值类型 方法名 (参数列表)”与父类的方法一样
 *               2)子类方法的修饰符不能小于父类方法的修饰符
 *               3)*若父类方法抛异常,那么子类方法抛的异常类型不能大于父类的。
 *               4)*子父类的方法必须同为static或同为非static的。
                 5)private 方法子类是不可见的,因此也不存在重写。子类中若有个这样的 private 方法,那这个方法与父类中的那个没有任何关系,是完全独立的。

super关键字:
lJava类中使用super来调用父类中的指定操作:
Øsuper可用于访问父类中定义的属性
Øsuper可用于调用父类中定义的成员方法
Øsuper可用于在子类构造方法中调用父类的构造
l注意:
Ø尤其当子父类出现同名成员时,可以用super进行区分
Øsuper的追溯不仅限于直接父
Øsuperthis的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识
(如果父类和子类中有同名的变量,则子类会有两个变量)。

* 3)super修饰构造器:通过在子类中使用“super(形参列表)”来显式的调用父类中指定的构造器。
 *    >在构造器内部,“super(形参列表)”必须要声明在首行!
 *    >在构造器内部,“this(形参列表)”或“super(形参列表)”只能出现一个!
 *    >当构造器中,不显式的调用“this(形参列表)”或“super(形参列表)”其中任何一个,默认调用的是
 *      父类空参的构造器!
 *    建议:设计一个类时,尽量要提供一个空参的构造器!

l子类中所有的构造默认都会访问父类中空参数构造
l父类中没有空参数的构造,子类的构造必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造,且必须放在构造器的第一行
l如果子类构造中既未显式调用父类或本类的构造,且父类中又没有无参的构造,则编译出错
(总之:子类对象的创建,一定会调用父类的构造器。)

子类对象实例化的过程:
会首先调用子类对象的所有直接父类和间接父类的构造器,由上到下,依次执行,然后再调用自己的构造器。


 * 面向对象的特征三:多态性
 * 1.多态性指的是什么?多态性,可以理解为一个事物的多种表型形态。
 *   1)方法的重载与重写  2)子类对象的多态性(父类引用指向子类对象)
 虚拟方法调用:通过父类的引用指向子类的对象实体,当调用方法时,实际执行的是子类重写父类的方法

 3.程序运行分为编译状态和运行状态。
 *   对于多态性来说,编译时,"看左边",将此引用变量理解为父类的类型
 *   运行时,"看右边",关注于真正对象的实体:子类的对象。那么执行的方法就是子类重写的。
4.子类对象的多态性,并不使用于属性。
父类和子类中有同名的变量,然后父类引用指向子类对象时,引用调用该变量时,是调用的父类的。
(方法子类可以重写或者说是覆盖,所以多态执行子类的方法,但是变量不存在覆盖的情况,子类中会有两个同名的变量,由于是父类的引用,所以调用时,会调用父类的变量。)

static关键字
* static修饰属性(类变量):
 * 1.由类创建的所有的对象,都共用这一个属性
 * 2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static修饰的属性,各个对象各自拥有一套副本)
 * 3.类变量随着类的加载而加载的,而且独一份
 * 4.静态的变量可以直接通过“类.类变量”的形式来调用
 * 5.类变量的加载是要早于对象。所以当有对象以后,可以“对象.类变量”使用。但是"类.实例变量"是不行的。
 * 6.类变量存在于静态域中。
 *
 * static修饰方法(类方法):
 * 1.随着类的加载而加载,在内存中也是独一份
 * 2.可以直接通过“类.类方法”的方式调用
 * 3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法是可以调用静态的属性或静态的方法(非静态可以访问静态,静态不可以访问非静态)
 *     >静态的方法内是不可以有this或super关键字的!
 * 注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,同时被回收也要晚于非静态的结构





类的第四个成员:初始化块(或代码块)
* 1.代码块如果有修饰的话,那么只能使用static。
 * 2.分类:
 * 静态代码块:
 * 1.里面可以有输出语句
 * 2.随着类的加载而加载,而且只被加载一次
 * 3.多个静态代码块之间按照顺序结构执行
 * 4.静态代码块的执行要早于非静态代码块的执行。
 * 5.静态的代码块中只能执行静态的结构(类属性,类方法)
 *
 * 非静态代码块:
 * 1.可以对类的属性(静态的 & 非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的 & 非静态的)
 * 2.里面可以有输出语句
 * 3.一个类中可以有多个非静态的代码块,多个代码块之间按照顺序结构执行
 * 4.每创建一个类的对象,非静态代码块就加载一次。
 * 5.非静态代码块的执行要早于构造器
 *
 * 关于属性赋值的操作:①默认的初始化②显式的初始化或代码块初始化(此处两个结构按照顺序执行) ③构造器中;④通过方法对对象的相应属性进行修改

final关键字:
*
 * final:最终的 ,可以用来修饰类、属性、方法
 *
 * 1.final修饰类:这个类就不能被继承。如:String类、StringBuffer类、System类
 *
 * 2.final修饰方法:不能被重写。如:Object类的getClass()
 *
 * 3.final修饰属性:此属性就是一个常量,一旦初始化后,不可再被赋值。习惯上,常量用大写字符表示。
 * 此常量在哪里赋值:①此常量不能使用默认初始化 ②可以显式的赋值、代码块、构造器。
 *
 * 变量用static final修饰:全局常量(如Math.PI)
 *
 * >与finally finalize()区分开



* abstract:抽象的
,可以用来修饰类、方法
 *
 * 1.abstract修饰类:抽象类
 * 1)不可被实例化
 * 2)抽象类有构造器 (凡是类都有构造器)(因为子类要访问父类的构造器)
 * 3)抽象方法所在的类,一定是抽象类。
 * 4)抽象类中可以没有抽象方法。
 * 5)抽象类的父类是object类
 *
 * 2.abstract修饰方法:抽象方法
 * 1)格式:没有方法体,包括{}.如:public abstract void eat();
 * 2)抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写此抽象方法。
 * 3)若子类继承抽象类,并重写了所有的抽象方法,则此类是一个"实体类",即可以实例化
 * 4)若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象的!


//abstract 不能用来修饰属性、构造器、不能与private、final、static同时存在
abstract就是用来让子类实现的,所以不能与private,final一起使用,static修饰的可以用类名直接调用,但是又是abstract的,显然不合理,所以不能与static同时存在。

接口:
l接口(interface)抽象方法常量值的定义的集合。
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现
有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果.(接口是跟类并列的一个概念,class有自己的一套体系,接口也有自己的一套体系)

 * 接口(interface)  是与类并行的一个概念
 * 1.接口可以看做是一个特殊的抽象类。是常量与抽象方法的一个集合,不能包含变量、一般的方法。
 * 2.接口是没有构造器的。(一个类肯定继承了另一个类,创建对象是访问的父类的构造器,跟接口没有关系。)
 * 3.接口定义的就是一种功能。此功能可以被类所实现(implements)。
 * 比如:class CC extends DD implements AA
 * 4.实现接口的类,必须要重写其中的所有的抽象方法,方可实例化。若没有重写所有的抽象方法,则此类仍为一个抽象类
 * 5.类可以实现多个接口。----java 中的类的继承是单继承的
 * 6.接口与接口之间也是继承的关系,而且可以实现多继承
 * >5,6描述的是java中的继承的特点。

//常量:所有的常量都用public static final修饰,可以省略
//抽象方法:所有的都用public abstract修饰,可以省略


类的成员之五:内部类

1.相当于说,我们可以在类的内部再定义类。外面的类:外部类。里面定义的类:内部类
 * 2.内部类的分类:成员内部类(声明在类内部且方法外的)  vs 局部内部类(声明在类的方法里)
 * 3.成员内部类:
 *         3.1是外部类的一个成员:①可以有修饰符(4个)②static final ③可以调用外部类的属性、方法
 *             
 *         3.2具体类的特点:①abstract ②还可以在其内部定义属性、方法、构造器
 *
 * 4.局部内部类:
 *
 * 5.关于内部类,大家掌握三点:
 *   ①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)(区分是否是static修饰的)
 *   ②如何区分调用外部类、内部类的变量(尤其是变量重名时)(内部类调用外部的属性Person.this.name)
 *   ③局部内部类的使用
(在下面)


class Person{
    String name = "韩梅梅";
    int age;
    //成员内部类(非static的)
    class Bird{
        String name = "黄鹂";
        int id;
        
        public Bird(){
            
        }
        public void setName(String name){
            System.out.println(name);//杜鹃
            System.out.println(this.name);//黄鹂
            System.out.println(Person.this.name);//韩梅梅
        }
        public void info(){
            show();
        }
    }
    //成员内部类(静态内部类)
    static class Dog{
        
    }
    
    public void show(){
        System.out.println("我是show()方法");
    }
    
    public void method1(){
        //局部内部类
        class A{
            
        }
    }
}


public static void main(String[] args) {
        //创建静态内部类的对象:可以直接通过外部类调用静态内部类的构造器
        Person.Dog d = new Person.Dog();
        //创建非静态的内部类的对象:必须先创建外部类的对象,通过外部类的对象调用内部类的构造器
        Person p = new Person();
        Person.Bird b = p.new Bird();//new p.Bird();
        b.info();
        b.setName("杜鹃");
    }



//局部内部类的使用
class OuterClass{

    //常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建
    //使用方式一
    public Comparable getComparable(){
        //1.创建一个实现Comparable接口的类:局部内部类
        class MyComparable implements Comparable{

            @Override
            public int compareTo(java.lang.Object o) {
                return 0;
            }
            
        }
        //2.返回一个实现类的对象
        return new MyComparable();
    }
    //使用方式二
    public Comparable getComparable1(){
        //返回一个实现Comparable接口的匿名内部类的对象
        return new Comparable(){

            @Override
            public int compareTo(java.lang.Object o) {
                // TODO Auto-generated method stub
                return 0;
            }
            
        };
    }
}

0 0