面向对象的概念:
1.面向过程:强调功能行为,过程。
例如:把大象装进冰箱里,先把冰箱门打开,大象装进去,冰箱门关上。操作的功能。
|
2.面向对象:把功能封装进对象,强调具备功能的对象(冰箱)。
|
类与对象的关系:
1类是对现实生活的抽象描述。
2对象就是现实生活中的实体。
例如:杯子是一类,而我桌子上摆的这个杯子就是一个对象。不管什么杯子有自己的容量、材质、颜色等共同属性,还可以用来喝水、观赏,这就是类的描述。
人是一个类,而我本人就是一个对象,我有自己的姓名、性别、身高、体重等静态属性,还有学习、跑步、走路等功能,这就是类的描述。
JAVA中的表现形式:
在JAVA中用class关键字表现类,class类似c语言的结构体,可以看做是一种数据类型,类中的描述:属性用各种不同的数据类型来表示,功能用方法表示。
对象通过new 类名 的方式得到一个对象,存储在堆内存中,并把引用指向 类名 xxx,xxx就相当于该对象的一个遥控器,如上图所示。
例如:
class Icebox { int wight;//冰箱的宽用一个int的数据类型表示 int height;//高也用一个int的数据类型表示 double price; //价格用一个double型的数据表示 //功能用方法表示 Public void open() { //打开方法 } } |
Icebox t = new Icebox(); 其中new Icebox();是位于堆内存中的真实对象,而t是一个Icebox类型的变量,是该对象的一个遥控器,一个冰箱可以有多个遥控器,而一个遥控器只能控制一台冰箱。 |
Icebox t = new Icebox(); 其中new Icebox();是位于堆内存中的真实对象,而t是一个Icebox类型的变量,是该对象的一个遥控器,一个冰箱可以有多个遥控器,而一个遥控器只能控制一台冰箱。 |
JAVA如何操作对象:
操作格式为:对象.对象成员
取得宽和高:t.weight 和 t.height
打开冰箱:t.open();
![]() |
成员变量和局部变量:
作用范围 | 内存中的位置 | |
成员变量 | 作用于整个类中,属于对象。 | 位于堆内存 |
局部变量 | 作用于方法(函数)中,或语句中。 | 位于栈中 |
静态变量 | 作用于类中,属于类,被对象共享。 | 位于方法区 |
主函数部分:
主函数格式:public void main(String [] args) {} ,主函数是程序运行的入口,JVM运行程序时,会去找该类的main方法。
匿名对象:
格式:new 类名();
代码示范 | 内存分析图 |
构造函数:
作用:给对象进行初始化,只有 new 对象,才调用一次构造函数,也只运行一次。
特点:
- l 函数名与类名相同
- l 不用定义返回值类型,不写void
- l 不可以写return语句
- l 不写构造函数,java自动使用默认构造函数,如果写了构造函数,java不会使用默认构造函数。
- l 构造方法同样具有方法重载的功能。
构造代码块:
作用:给对象进行初始化,优于构造函数执行
区别:给所有对象进行统一初始化
用法:用于对所有对象的共性进行初始化,也可以直接在变量定义时初始化。
示例:
public class Person { private String name; private int age; { System.out.println("//构造代码块"); } public Person(String name, int age) { this.name= name; this.age = age; } public Person() { } } |
this关键字:
作用1:指明为当前使用的对象,通常用于区别局部变量和成员变量,该对象与其他对象。
为了能用渐变、面向对象的语法来编写代码——即“发送消息给对象”,编译器做了一些幕后工作。它暗自把“所操作对象的引用”作为第一个参数传递给“方法”,例如:
假设person有一个peel()方法。 Public void peel(int i){ } Person p = new Person(); p.peel(5); | 其实内部的表示形式是: p.peel(p,5); |
注意:只有当需要明确指出对当前对象的引用时,才需要使用this关键字。例如,当需要返回时。
示例:
public class Person { private String name; private int age; public Person(String name, int age) { this.name /*指明当前使用的对象的属性name*/= name;//name为方法的参数 this.age = age; } } |
public class Person { private String name; private int age; public Person(String name, int age) { this(); } public Person() { System.out.println("无参构造方法"); } } |
static关键字
Static方法就是没有this的方法。不是通过“向对象发送消息”动的方式完成的。
注意事项:在static方法的内部不能调用非静态方法,反过来是可以的。
Static的真正用途:在没有创建任何对象的前提下,仅通过类本身来调用static方法。(java中禁止使用全局方法,但你在类中置入static方法就可以访问其他的static方法和static域)。
代码示例:
class Seven { public int id_num = 0;//非静态属性 public static int id = 0;//静态属性 //静态方法 public static void show() { unshow(); } //非静态方法 public void unshow() { } //错误提示: /*无法从静态上下文中引用非静态 方法 unshow() unshow();*/ } |
成员初始化
Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,java以编译时错误的形式贯彻这种保证。
- 类的每个基本类型数据成员保证都会有一个初始值。
- 在类中定义一个对象引用时,如果不将其初始化,此引用就会获得一个特殊值null。
- 在类的内部,变量定义的先后顺序决定了初始化的顺序。
指定初始化:
- l 在定义类成员变量的地方为其赋值
初始化基本类型数据 public class Init { boolean bool = true; char ch = 'x'; byte b = 47; short s = 0xff; int i = 99; long l = 1; float f = 3.14f; double d = 3.14159; } | 初始化非基本类型数据 class Depth{} public class Mess { Depth d = new Depth(); } //如果没有为d指定初始值就尝试使用它,就会出现运行时错误,报告空指针异常。 |
- 通过调用某一方法来提供初值
class MethodInit { int i = f(); int f() {return 11;} } | 向前引用的错误示例: class MethodInit { int j = g(i); int i = f(); int f() {return 11;} int g(int n) {return n*10;} } |
构造器初始化:
可以用构造器进行初始化。在运行时刻,可以调用方法或执行某些动作来确定初值,但是无法阻止自动初始化的进行,他将在构造器被调用之前发生,也就是说在类刚被加载时进行。
class Counter { int i; Counter() {i = 7;} } | i首先会被置为0,然后变成7。对于所有基本类型和对象引用,包括在定义时指定的变量都会进行自动初始化,赋予默认值 |
静态数据的初始化:
无论穿件多少个对象,静态数据都只占用一份存储区域。如果未进行初始化,那么它就会获得基本类型的标准初值,如果是一个对象引用,那么它的默认初始化值就是null。
静态初始化只有在必要时刻才会进行。
总结对象创建过程:假设有个Dog类
1. 即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位Dog.class文件。 |
2. 然后载入Dog.class(创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。 |
3. 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。 |
4. 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说是0,布尔类型和字符型也相同,引用类型被设置成了null)。 |
5. 执行所有出现于字段定义处的初始化动作。 |
6. 执行构造器。 |
可变参数列表
Java SE5以前 | Java SE5以后 |
class VarArgs { static void printArray(Object[] args) { for(Object obj : args) { System.out.print(obj + " "); System.out.println(); } } public static void main(String [] args) { printArray(new Object[]{new Integer(47),new Float(3.14),new Double(11.11)}); printArray(new Object[]{new A(),new A(),new A()}); } } 输出:47 3.14 11.11 A@1a46e30 A@3e25a5 A@19821f | class VarArgs { static void printArray(Object... args) { for(Object obj : args) { System.out.print(obj + " "); System.out.println(); } } public static void main(String [] args) { printArray(new Integer(47),new Float(3.14),new Double(11.11)); printArray(new A(),new A(),new A()); } } 输出:47 3.14 11.11 A@1a46e30 A@3e25a5 A@19821f |
面向对象的三大特征:封装、继承、多态。
封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
- 将变化隔离:更改内部实现,外部调用方式不变。
- 便于使用:相比面向过程,更方便。
- 提高重用性:可以被多次使用。
- 提高安全性:阻止修改重要的代码。
- 封装原则:
- 将不需要对外提供的内容都隐藏起来
- 将属性隐藏,提供公共访问方法对其访问。
代码示例:
public class Person { private String name; private int 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; } } |