----------- android培训java培、期待与您交流!------------

此博文涉及的主要知识点:

   1.理解面向对象

   2.类与对象的关系

   3.匿名对象

   4.封装概述

   5.构造函数

   6.对象加载

   7.this关键字

   8.static关键字

   9.静态的应用

   10.main函数

   11.类的访问权限


一、理解面向对象

1、面向对象编程:OOP:Object Oriented Programming

2、面向对象:将复杂的事情简单化、面向对象以前的过程中的执行者,变成了指挥者、面向对象这种思想是符合

现在人们思考习惯的一种思想。

3、面向对象的三大基本特征:封装、继承、多态。判断一门语言是否是面向对象的,通常可以使用继承和多态

来加以判断。例如,JavaScript语言就是基于对象的,它使用一些封装好的好象,调用对象的方法,修改对象

的属性;但是它们无法让开发者派生出新的类,开发者只能使用现有对象的方法和属性。

4、面向对象基于面向过程的,它们都是一种思想。面向过程强调的是功能行为,而面向对象将功能封装进对象

,强调具备了该功能的对象。

5、如:人关门这一动作:(名词提炼法)

面向过程思想来理解,一切以函数为中心,那么会用如下语句来表达:

//关(人,门)

面向对象思想来理解,一切以对象为中心,那么会用如下语句来表达:

//人.关(门);

要知道,只有门才有关的动作,人只是作为了指挥者,指挥门去关门。


二、类与对象的关系

1、类:对象的蓝图,生成对象的模板,是对一类事物的描述,是抽象的概念上的定义。

对象:对象是实际存在的该类事物的每个个体,因而也称为实例

2、类之间的三种关系:依赖关第(uses-a)聚焦关系(has-a)继承关系(is-a)

3、在java中,类和对象的关系就像动物和老虎的关系一样,老虎属于动物,老虎只是动物的一个实例。

4.类中定义的属性是一种可存储值的变量,该变量代表着事物的具体性质。属性对应是类中的变量,行为对应的

是类中的函数,其实定义类,就是在描述事物,就是在定义属性和方法,属性和行为共同成为类

中的成员(成员变量和成员函数)

/*
扩展:
    成员变量和局部变量:
        定义的位置:
            成员变量直接定义在类中
            局部变量定义在方法中,参数上,语句中。
        作用范围:
            成员变量作用于整个类中。
            局部变量作用于所属大括号内,大括号结束,局部变量就失去了作用域。
        在内存中的位置:
            成员变量在堆内存中,随着对象的产生而存在,消失而消失。
            局部变量:存在栈内存中,随着所属区域的运行而存在,结束而释放。
*/


三、匿名对象

注意:匿名对象调用属性没有意义。

//定义一个Person类
class Person
{
    //定义属性。
    String name = "zhangsan";
    int age = 23;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    //定义方法
    void run()
    {
        System.out.println(name+"....."+age);
    }
}
class AnnoymousObject
{
    public static void main(String[] args)
    {
        /*
        匿名对象使用方式一:
            当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。
            当对象对成员进行多次调用时,不能使用匿名对象,必须给对象起名字。
        //普通方式
        Person p = new Person();
        p.run();
        p.age = 24;
        //匿名方式
        new Person().run();
        */
        //普通方式
        Perosn p2 = new Person();
        show(p2);
        //匿名方式
        show(new Person());
    }
    //匿名对象使用方式二:
        //可以将匿名对象作为实际参数进行传递。
    public static void show(Person pNew)
    {
        pNew.name = "lisi";
        pNew.age = 34;
        pNew.run();
    }
}


四、封装概述(封装Encapsulation)

1、封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。

2、目的:增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。

3、好处:将变化隔离、便于使用、提高重用性、提高安全性。

4、封装原则:

  • 将不需要对外提供的内容都隐藏起来

  • 把属性都隐藏,提供公共方法对其访问。

5、函数就是java中最小的封装体。

6、关于private

  • private int age;//私有的访问权限最低,只有在本类中的访问有效。

  • 注意:私有仅仅是封装的一种体现形式而己。

  • 私有的成员:其他类不能直接创建对象访问,所以只有通过本类对外提供具体的访问方式来完成对私有的访问。

  • 可以通过对外提供函数的形式对其进行访问。

  • 好处:可以在函数中加入逻辑判断等操作,对数据进行判断等操作。

  • 总结:开发时,记住,属性是用于存储数据的。直接被访问,容易出现安全隐患。所以,类中的属性通常被私有化,并对外提供公共的访问方法。这个方法一般有两个,规范写法:对于属性xxx,可以使用setXXX,getXXX()对其进行操作。


五、构造函数

class Perosn
{
    //定义属性
    private String name;
    private int age;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    //构造函数1
    Person()
    {
        System.out.println("A:name="+name+",age="+age);
        cry();
    }
    //构造函数2
    Person(String n)
    {
        name = n;
        System.out.println("B:name="+name+",age="+age);
        cry();
    }
    //构造函数2
    Person(String n, int a)
    {
        name = n;
        age = a;
        System.out.println("C:name="+name+",age="+age);
        cry();
    }
    public void cry()
    {
        System.out.println("cry......");
    }
    /*
    省略了get和set方法....
    */
}

1、构造函数:用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种

2、特点:

  • 1:该函数的名称和所在类的名称相同

  • 2:不需要定义返回值类型

  • 3:该函数没有具体的返回值

3、记住:所有对象创建时,都需要初始化才可以使用

4、注意:

  • 一个类在定义时,如果没有定义过构造函数。那么该类中会自动生成一个空参数的构造函数。

为了方便该类创建对象,完成初始化。如果在类中自定义了构造函数。那么默认的构造函数就没有了

简单一句话:你写了,默认就没有了。你没写就只有默认的

  • 一个类中,可以有多个构造函数,因为它们的函数名称都相同,所以只能通过参数列表来区分。

所以,一个类中如果出现多个构造函数。它们的存在是以重载体现的

5、构造函数和一般函数有什么区别呢?

  1. 两个函数定义格式不同。

  2. 构造函数是在对象创建时,就被调用,用于初始化,而且初始化动作只执行一次。一般函数,是对象创建后,需要调用才执行,可以被调用多次。

6、什么时候使用构造函数呢?

   分析事物时,发现具体事物一出现,就具备了一些特征,那就将这些特征定义到构造函数内,并思考在对构造函数进行定义的时候需不需要未知内容参与运算,如需要就定义参数。

7、构造代码块和构造函数有什么区别?

  • 构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用。

  • 一个代码块,只要对象一建立,就会调用这个代码块。

  • 构造函数:是给与之对应的对象进行初始化,它具有针对性。


六、Person p = new Person();创建一个对象都在内存中做了什么事情?

1、先将硬盘上指定位置的Person.class文件加载进内存。

2、执行main方法时,在栈内存中开辟了main方法的空间(压栈一进栈),然后在main方法的栈区分配了一个变量P。

3、在堆内存中开辟一个实体空间,分配了一个内存首地址值。new

4、在该实体空间中进行属性的空间分配,并进行了默认初始化。

5、对空间中的属性进行显示初始化。

6、进行实体的构造代码块初始化。

7、调用该实体对应的构造函数,进行构造函数初始化。

8、将首地址赋值给p,P变量就引用了该实体。(指向了该对象)


七、this关键字

1、this:代表对象。就是所在函数所属对象的引用

2、this到底代表什么呢?哪个对象调用了this所在的函数。this就代表哪个对象。就是哪个对象的引用

3、开发时,什么时候使用this呢?

   在定义功能时,如果该功能内部使用到了调用该功能的对象。这时就用this来表示这个对象

4、this还可以用于构造函数间的调用。

5、调用格式:this(实际参数);

  • this对象后面跟上.调用的是成员属性和成员方法(一般方法);

  • this对象后面跟上()调用的是本类中的对应参数的构造函数。

6、注意:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初始化动作一定要执行。否则编译失败。


八、static关键字

1、static,是一个修饰符,用于修饰成员(成员变量和成员函数)。

2、有以下三个特点:

(1)、想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。

class Person
{
    String name;
    static String country = "CN";
    /*此处略构造函数和get、set方法以及主函数。
    ....
    ....
    */
                                                                                                                                                                                                                                                                                                                                                                                                                                
    Person p = new Person();
}
/*
    当Person p = new Person();运行时,系统就会在堆内存中开辟一个内存空间,
    存放new Person();它有name和country = "CN"两属性,但当多个用户建立时,
    "CN"这个数据就会占用比较多的空间,为了节省空间,运用修饰符static,这样
    country = "CN"就被共享,从而节省空间,共享把country = "CN"从堆内存中提
    取出来供多个用户使用。
    这时 country = "CN" 所在区为:数据区,方法区,共享区或常量池。
*/

(2),被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。

Person p = new Person();
System.out.println(p.country);
System.out.println(Person.country);

(3),静态随着类的加载而加载。而且优先于对象存在。

①String name;
②static String country = "CN";
/*
当class Person加载到内存中时,②加载到了内存中,
而①没有,只有建立对象时,①才会加载
*/

3、弊端:

①有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。

②静态方法只能访问静态成员,不可以访问非静态成员。因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。

③静态方法中不能使用this, super关键字。因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。

④主函数是静态的。

4、什么时候定义静态成员呢?或者说:定义成员时,到底需不需要被静态修饰呢?

成员分两种:

①成员变量。(数据共享时静态化)

该成员变量的数据是否是所有对象都一样:

如果是,那么该变量需要被静态修饰,因为是共享的数据。

如果不是,那么就说这是对象的特有数据,要存储到对象中。

②成员函数。(方法中没有调用对象特有数据(非静态数据)时就定义成静态)

   如果判断成员函数是否需要被静态修饰呢?

   只要参考,该函数内是否访问了对象中的特有数据:

  • 如果有访问特有数据,那方法不能被静态修饰。

  • 如果没有访问过特有数据,那么这个方法需要被静态修饰。

5、成员变量和静态变量的区别:

  • 成员变量所属于对象。所以也称为实例变量

   静态变量所属于类。所以也称为类变量

  • 成员变量存在于堆内存中

   静态变量存在于方法区中

  • 成员变量随着对象创建而存在。随着对象被回收而消失

   静态变量随着类的加载而存在。随着类的消失而消失

  • 成员变量只能被对象所调用

   静态变量可以被对象调用,也可以被类名调用。

所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。静态的注意:静态的生命周期很长。

6、静态代码块:就是一个有静态关键字标识的一个代码块区域。定义在类中。

作用:可以完成类的初始化。

静态代码块随着类的加载而执行,而且只执行一次(new多个对象就只执行一次)。如果和主函数在同一类中,优先于主函数执行。


九、静态的应用

class Demo
{
    public static void main(String[] args)
    {
        int[] arr = {3, 4, 1, 8};
        int[] arr2 = {3, 6, ,7 ,12};
        int max = getMax(arr);
        System.out.println("max="+max);
    }
    /*当我们需要对另外的一个或多个类似的数组进行取最大值时,
    这时候就不能像如上重复代码了,需要抽取方法,提高代码的封装性。如下:
    */
    public static int getMax(int[] arr)
    {
        int max = 0;
        for (int x = 1; x < arr.length; x++)
        {
            if(arr[x] > arr[max])
                max = x;
        }
        return arr[max];
    }
}
/*很有可能,另一对象也需要获取int数组的最大值,而上面只getMax方法定义在函数中,不能使用
这时,我们又要定义一个getMax的方法。*/
class Test
{
    public static int getMax(int[] arr)
    {
        int max = 0;
        for (int x = 1; x < arr.length; x++)
        {
            if(arr[x] > arr[max])
                max = x;
        }
        return arr[max];
    }
}

   如上,我们发现多个对象有相同的功能,想想,我们能否把相同的功能单独封装进一个对象,便于使用呢?

class ArrayTool
{
    /*将方法都静态后,可以方便使用,但是该类还是可以被其它程序建立对象的,为了
        更为严谨,强制让该类不能建立对象,可以通过构造函数私有完成。*/
    private ArrayTool(){}
    //定义一个取最大值的函数
    public static int getMax(int[] arr)
    {
        int max = 0;
        for (int x = 1; x < arr.length; x++)
        {
            if(arr[x] < arr[min])
                min = x;
        }
        return arr[min];
    }
    //定义一个取最小值的函数
    public static int getMin(int[] arr)
    {
        int min = 0;
        for (int x = 0; x < arr.length; x++)
        {
            if(arr[x] < arr[min])
                min = x;
        }
        return arr[min];
    }
    //定义一个排序功能:选择排序
    public static void selectSort(int[] arr)
    {
        for (int x = 0; x < arr.length-1; x++)
        {
            for (int y = x+1; y < arr.length; y++)
            {
                if(arr[x] > arr[y])
                {
                    swap(arr, x , y);
                }
            }
        }
    }
    //另定义一个排序功能:冒泡排序
    public static void bubbleSort(int[] arr)
    {
        for(int x = 0; x< arr.length-1; x++)
        {
            for(int y = 0; y < arr.length-x-1; y++)
            {
                if(arr[y] > arr[y+1])
                {
                    swap(arr, y, y+1)
                }
            }
        }
    }
    //因为排序功能,都要交换元素位置,所以单独封装进一个函数。
    private static void swap(int[] arr, int a, int b)
    {
        int temp  = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}
class ArrayToolDemo
{
    public static void main(String[] args)
    {
        int[] arr = {3, 1, 5, 12, 34};
        int max  = ArrayTool.getMax(arr);
        System.out.println("max="+max);
        /*
        ArrayTool tool = new ArrayTool();
        int max = tool.getMax(arr);
        System.out.println("max="+max);
        int min = too.getMin(arr);
        System.out.println("min="+min);
        */
        //如果我们要来个新的数组。一样要获取最大值等功能。
        /*
        int[] arr1 = {3, 4, 54, 6, 7};
        ArrayTool tool1 = new ArrayTool();
        */
        /*
        虽然可以通过建立ArrayTool的对象使用这些工具方法,
        对数组进行操作。
        发现了问题:
        1,对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。
        2.操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。
        这时就要考虑,让程序更严谨,是不需要对象的。
        可以将ArrayTool中的方法都定义成static的,直接通过类名调用即可。
        */
    }
}


十、main函数

public static void main(String[] args)

1、主函数:是一个特殊的函数,作为程序的入口,可以被jvm调用。

2、主函数的定义:

public:代表着该函数的访问权限是最大的。

static:代表主函数随着类的加载就已经存在了。它不需要对象,直接类名即可。

void:主函数没有具体的返回值。

main:不是关键字,但是一个特殊的单词,可以被jvm识别。(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。

3、主函数是固定格式的:jvm识别。

4、jvm在调用主函数时,传入的是new String[0];

class MainDemo
{
    public static void main(String[] args)
    {
        String[] arr = {"haha","hehe"};
        MainTest.main(arr);
    }
}
class MainTest
{
    public static void main(String[] args)
    {
        for (int x = 0; x < args.length; x++)
        {
            System.out.println(args[x]);
        }
    }
}


十一、类的访问权限

1、public:

   对于成员来说:任何其他类都可以访问它们,不管在同一个包中还是在另外的包中。对于类来说:也是一样。

2、default:

   对于成员来说:如果一个类的成员没有任何权限修饰,那么它门就是缺省包访问权限,用default来表示,注意default不是访问权限。同一个包内其它类可以访问,但包外就不可以。对于同一个文件夹下的、没有用package的classes,Java会自动将这些classes初见为隶属于该目录的default package,可以相互调用class中的defaulty成员。如以下两个class分别在同一个文件夹的两个文件中,虽然没有引入package,但隶属于相同的default package.对于类来说:同一个包中的类可以用。总之,类只可以声明为public或者default。

3、private:

  • 对于对于成员来说:只能在该成员隶属于的类中访问。

  • 对于类来说:类不可以声明为private.

4、protected:

   对于对于成员来说:相同包中的类可以访问(包访问权限);基类通过protected

   把基类中的成员的访问权限赋予派生类不是所有类(派生类访问权限)。

   对于类来说:类不可以声明为protected

5、说明:

  • 每个编译单元(类文件)都仅能有一个public class。

  • public class的名称(包含大小写)必须和其类文件同名。

  • 一个类文件(*.java)中可以不存在public class。

 这种形式的存在的场景:如果我们在某个包内撰写一个class,仅仅是为了配合同包内的其他类工作,而且我们不想再为了撰写说明文档给客户(不一定是现实意义的客户,可能是调用这个类的类)看而伤脑筋,而且有可能过一段时间之后有可能会彻底改变原有的做法,并完全舍弃旧版本,以全新的版本代替。

  • class不可以是private和protected。

  • 如果不希望那个任何产生某个class的对象,可以将该类得所有构造函数设置成private。但是即使这样也可以生成该类的对象就是class的static的成员(属性和方法)可以办到。


十二、其它一些问题

1、过程和对象在我们的程序中是如何体现的呢?

   过程其实就是函数。

   对象是将函数等一些内容进行了封装。

2、类中怎么没有定义主函数呢?

   注意:主函数的存在,仅为该类是否需要独立运行。如果不需要,主函数是不用定义的。

3.静态代码块、构造代码块、构造函数同时存在时的执行顺序:

   静态代码块一构造代码块一构造函数;


----------- android培训java培、期待与您交流!------------