1.面向对象与面向过程的理解
我们学习C语言时常用的思考方式是面向过程,面向过程即针对一个特定的问题去思考其解决步骤,一般较为简单,例如:做饭、洗澡、学车等,像这类我们都可以采用第一步干什么,第二步干什么的方式去思考。而面向对象则很难分出第一步做什么,第二步做什么。面向对象离不开面向过程,我们可以把面向对象当做一个个面向过程的组合,就比如造车,面向对象就是思考车这个对象是由什么组成的,而每一个零件的制作就是一个个过程要经过一道道工序才能做出来。因此,面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。 但是,具体到实现部分的微观操作(就是一个个方法),仍然需要面向过程的思路去处理。
2.对栈、堆和方法区的理解
Java虚拟机的内存分析是一个很重要的知识点。其内存可以分为三个区域:栈stack、堆heap、方法区method area。
栈
方法执行的内存模型 方法被调用时都会创建一个栈帧用来存储 局部变量 操作数 方法出口
线程私有的 每个线程只有一个栈
栈是一个连续的内存空间
栈(stack)相对整个系统而言,调用栈(Call stack)相对某个进程而言,栈帧(stack frame)则是相对某个函数而言,调用栈就是正在使用的栈空间,由多个嵌套调用函数所使用的栈帧组成。具体来说,Call stack就是指存放某个程序的正在运行的函数的信息的栈。Call stack 由 stack frames 组成,每个 stack frame 对应于一个未完成运行的函数。
栈用来传递函数参数,存储返回值信息,保存寄存器以供恢复调用前处理机状态。每次调用一个函数,都要为该次调用的函数实例分配栈空间。为单个函数分配的那部分栈空间就叫做 stack frame,也就是说,stack frame 这个说法主要是为了描述函数调用关系的。
什么是进程(Process):普通的解释就是,进程是程序的一次执行,而什么是线程(Thread),线程可以理解为进程中的执行的一段程序片段。在一个多任务环境中下面的概念可以帮助我们理解两者间的差别:
进程间是独立的,这表现在内存空间,上下文环境;线程运行在进程空间内。 一般来讲(不使用特殊技术)进程是无法突破进程边界存取其他进程内的存储空间;而线程由于处于进程空间内,所以同一进程所产生的线程共享同一内存空间。 同一进程中的两段代码不能够同时执行,除非引入线程。 线程是属于进程的,当进程退出时该进程所产生的线程都会被强制退出并清除。线程占用的资源要少于进程所占用的资源。 进程和线程都可以有优先级。在线程系统中进程也是一个线程。可以将进程理解为一个程序的第一个线程。
堆
存放创建好的对象
被所有线程共享
堆是一个不连续的内存空间
方法区
JVM只有一个方法区 所有线程共享
本质也是堆 只是用来存储类、常量相关的信息
用来存放程序中永远不变或唯一的内容,所以又叫静态区
举例:
AppMain.java
public class AppMain {//运行时, jvm 把appmain的信息都放入方法区
public static void main(String[] args) { //main 方法本身放入方法区。
Sample test1 = new Sample( " 测试1 " ); //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面
Sample test2 = new Sample( " 测试2 " );
test1.printName();
test2.printName();
}
}
Sample.java
public class Sample { //运行时, jvm 把appmain的信息都放入方法区
private name;/** 范例名称 */ //new Sample实例后, name 引用放入栈区里, name 对象放入堆里
public Sample(String name) {/** 构造方法 */
this .name = name;
}
public void printName() { //print方法本身放入 方法区里。
System.out.println(name);/** 输出 */
}
}
3.构造方法(构造器)
构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法**。构造方法和其他方法一样也可以重载**。通过一个类创建一个对象,这个过程叫做实例化 。 实例化是通过调用构造方法实现的 。
构造方法是一种特殊的成员方法,它的特殊性反映在如下几个方面:
1.构造方法作用:(1).构造出来一个类的实例 (2).对构造出来个一个类的实例(对象)初始化。
2.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
3.主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。
4.类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。
5.不能被static、final、synchronized、abstract和native修饰。
6.构造方法在初始化对象时自动执行,一般不能显式地直接调用.当同一个类存在多个构造方法时,java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应。完成构造函数的调用。
7.构造方法分为两种:无参构造方法 有参构造方法
构造方法可以被重载。没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。
public class Hero {
public void attack(Hero hero) {//普通方法
}
public void heal() {//无参方法
}
public static void main(String[] args) {
Hero h = new Hero();//前半部分,Hero h的意思是,在内存中分配一个变量,名字叫h,这个变量是Hero类型的;后半部分,new Hero();这就是new关键字和构造方法来创建一个对象,Hero()是构造方法的名字。
Hero h2 = new Hero();
h.attack(h2);//普通方法必须要先设置,才能调用,而构造方法不需要
h.heal();
}
}
Java中使用 new关键字加上构造方法,来创建一个对象,一个普通类在没有实例化之前,就是new之前,它的属性,方法等等在内存中都是不存在的。只有使用new了以后,这个类的一些东西在内存中才会真的存在,也就是说只有new了之后,这个类才能用。new的意思是创建一个新的实例。
想造出一个对象来,需要运用;new Hero(); 说明 new这个Hero类的一个对象,程序运行的时候,会调用构造方法Hero(),等这个构造方法执行完了,这个Hero类型的对象也就造出来了,真正的出现在内存当中了。
使用new关键字造出来的对象,被分配在内存的堆区(heap),而且等这个对象真正出来之后,还会做一件重要的事情:new关键字创建出一个对象之后,会把这个对象在内存中的地址返回,通过这个地址就可以找到这个对象。
那么上面的写法,Hero h = new Hero();意思就是说,把这个对象在内存中的地址 赋值 给变量h,这就是Java中引用概念,h就叫做引用,或者叫引用变量,或者直接叫变量,没问题,都是它;h的值就是一个内存地址,或者叫引用地址。
通过这个地址,就可以准确的找到刚才创建出来的对象,以后我们要使用这个对象做一些事情,调用此对象的方法什么的,都用过这个引用。
扩展资料
创建一个对象并将其赋值给一个引用变量:
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);
第一行创建了一个 Point 类的对象,第二个和第三个线创建一个Rectangle 矩形类的对象。
这些陈述中的每一个都有三个部分(详细讨论):
- 声明Declaration:粗体代码是将变量名称与对象类型关联的变量声明。
- 实例化Instantiating :new关键字是一个java运算符,它用来创建对象。
- 初始化Initialization:new运算符,随后调用构造函数,初始化新创建的对象。
声明一个变量来指向一个对象,即引用。
在此之前,要声明一个变量,需要写:type name(类型名)
这将告诉编译器将使用name引用一个type类型的对象。用一个原始变量,这个声明也保留了适当的内存量的变量。
-
你也可以在自己的行上声明一个引用变量。例如:
Point originone;
如果只是声明一个像originone这样的引用变量,其价值将待定,直到有一个对象真正被创造和分配给它。只是简单地声明一个引用变量而并没有创建一个对象。 -
对于这样,需要使用new运算符。在代码中使用它之前,必须指定一个对象给originone。否则,会得到一个编译器错误-----空指针异常。
处于这种状态的变量,目前没有引用任何的对象,可以说明如下(变量名,originone,一个引用没指向任何对象)。 -
例化一个类对象:
new运算符实例化一个类对象,通过给这个对象分配内存并返回一个指向该内存的引用。new运算符也调用了对象的构造函数。
注意:实例化一个类的对象的意思就是创建对象。创建对象时,正在创造一个类的实例,因而实例化一个类的对象。 -
new运算符需要一个单一的,后缀参数,需要调用构造函数。构造函数的名称提供了需要实例化类的名称。
-
new运算符返回它所创建的对象的引用。此引用通常被分配给一个合适的类型的变量,如:Point originone =new Point(23,94);
-
由new运算符返回的引用可以不需要被赋值给变量。它也可以直接使用在一个表达式中。