当前位置:文档之家› JAVA核心机制介绍

JAVA核心机制介绍

JAVA核心机制介绍
JAVA核心机制介绍

1 JAVA内存管理

1.1 java是如何管理内存的

Java的内存管理就是对象的分配和释放问题。(两部分)

分配:内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间(基本类型除外),所有的对象都在堆(Heap)中分配空间。

释放:对象的释放是由垃圾回收机制决定和执行的,这样做确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,

GC(Gabage Collection)为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。

1.2什么叫java的内存泄露

在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连(也就是说仍存在该内存对象的引用);其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。

与C++内存泄露概念的区别:

在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。

1.3JVM的内存区域组成

java把内存分两种:一种是栈内存,另一种是堆内存

1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;

2。堆内存用来存放由new创建的对象和数组以及对象的实例变量

在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理。

堆和栈的优缺点

堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。另外,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

Java的内存管理实质上就是JVM的内存管理,JVM的内存分为两部分:stack和heap Stack(栈)是指JVM的内存指令区。Java基本数据类型,Java指令代码,常量都存在stack中。

heap(堆)是JVM的内存数据区。heap专门用来保存对象的实例,实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中),对象实例在heap中分配好后需要在Stack中保存1个4字节的heap 内存地址,用来定位该对象在heap中的位置,以便找到该对象实例。

Stack不存在内存管理问题,系统自动管理,heap中的对象由GC负责垃圾回收。

GC垃圾收集的规程:GC进程定期扫描heap,他根据stack中保存的4字节对象地址扫描heap,定位heap中的这些对象,进行一些优化,并且假设heap中的没有扫描到区域都是空闲的,统统refresh(实际上是把stack中丢失对象地址的无用对象清除了)。这就是垃圾回收的过程。

关于对象

1、方法本身是指令的操作码部分,保存在stack中;

2、方法内部变量作为指令的操作数部分,跟在指令的操作码之后,保存在stack中(实际上是简单类型保存在stack中,对象实例在stack中保存地址,在heap中保存值)

上述的指令操作数和指令操作码构成完整的Java指令。

3、对象实例包括属性值作为数据,保存在heap中。

关于静态方法和静态属性

当一个ClassLoader load进入JVM后,方法指令保存在stack中,此时heap区没有数据,然后程序计数器开始执行指令,如果是一个静态方法,直接依次执行指令代码,当然此时指令代码无法访问heap数据区;如果是非静态方法,由于隐含参数没有值,会报错。因此在非静态方法执行之前,要先new对象,在heap中分配数据,并把stack中的地址指针交给非静态方法,这样程序计数器一次执行指令,而指令代码就能够访问到heap数据区。

由于上述的原因,静态属性是保存在stack中的(基本类型保存在stack,对象类型地址保存在stack中,值保存在heap中),并因此具有全局属性。

补充:字符串常量在stack分配,this在heap中分配,数组想对象一样既在stack中分配地址放数组名称,又在heap中分配数组实际大小的空间。

下面再说C/C++内存管理

在C++中,内存分为5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

栈:编译器自动管理,里面的变量是局部变量、函数参数等(可以用alloca函数分配)堆:由new分配的内存块,用delete释放

自由存储区:由malloc分配,用free释放和堆很相似

全局/静态存储区:全局变量和静态变量

常量存储区:常量

1.3.1 JVM中的对象生命周期

在JVM运行空间中,对象的整个生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段(Finalized)与释放阶段(Free)。上面的这7个阶段,构成了 JVM 中对象的完整的生命周期。下面分别介绍对象在处于这7个阶段时的不同情形。

3.1.1创建阶段

在对象创建阶段,系统要通过下面的步骤,完成对象的创建过程:

(1)为对象分配存储空间。(2)开始构造对象。(3)递归调用其超类的构造方法。(4)进行对象实例初始化与变量初始化。(5)执行构造方法体。

上面的5个步骤中的第3步就是指递归地调用该类所扩展的所有父类的构造方法,一个Java类(除Object类外)至少有一个父类(Object),这个规则既是强制的,也是隐式的。你可能已经注意到在创建一个Java类的时候,并没有显式地声明扩展(extends)一个Object 父类。实际上,在 Java程序设计中,任何一个Java类都直接或间接的是Object类的子类。例如下面的代码:

public class A {

}

这个声明等同于下面的声明:

public class A extends https://www.doczj.com/doc/a615327380.html,ng.Object {

}

上面讲解了对象处于创建阶段时,系统所做的一些处理工作,其中有些过程与应用的性能密切相关,因此在创建对象时,我们应该遵循一些基本的规则,以提高应用的性能。

下面是在创建对象时的几个关键应用规则:

(1)避免在循环体中创建对象,即使该对象占用内存空间不大。

(2)尽量及时使对象符合垃圾回收标准。

(3)不要采用过深的继承层次。

(4)访问本地变量优于访问类中的变量。

关于规则(1)避免在循环体中创建对象,即使该对象占用内存空间不大,需要提示一下,这种情况在我们的实际应用中经常遇到,而且我们很容易犯类似的错误,例如下面的代码:

……

for (int i = 0; i < 10000; ++i) {

Object obj = new Object();

System.out.println("obj= "+ obj);

}

……

上面代码的书写方式相信对你来说不会陌生,也许在以前的应用开发中你也这样做过,尤其是在枚举一个Vector对象中的对象元素的操作中经常会这样书写,但这却违反了上述规则(1),因为这样会浪费较大的内存空间,正确的方法如下所示:

……

Object obj = null;

for (int i = 0; i < 10000; ++i) {

obj = new Object();

System.out.println("obj= "+ obj);

}

……

采用上面的第二种编写方式,仅在内存中保存一份对该对象的引用,而不像上面的第一种编写方式中代码会在内存中产生大量的对象应用,浪费大量的内存空间,而且增大了系统做垃圾回收的负荷。因此在循环体中声明创建对象的编写方式应该尽量避免。

另外,不要对一个对象进行多次初始化,这同样会带来较大的内存开销,降低系统性能,如:

public class A {

private Hashtable table = new Hashtable ();

public A() {

// 将Hashtable对象table初始化了两次

table = new Hashtable();

}

}

正确的方式为:

public class B {

private Hashtable table = new Hashtable ();

public B() {

}

}

不要小看这个差别,它却使应用软件的性能相差甚远,如图2-5所示。

图2-5 初始化对象多次所带来的性能差别

看来在程序设计中也应该遵从“勿以恶小而为之”的古训,否则我们开发出来的应用也是低效的应用,有时应用软件中的一个极小的失误,就会大幅度地降低整个系统的性能。因此,我们在日常的应用开发中,应该认真对待每一行代码,采用最优化的编写方式,不要忽视细节,不要忽视潜在的问题。

3.1.2应用阶段

当对象的创建阶段结束之后,该对象通常就会进入对象的应用阶段。这个阶段是对象得以表现自身能力的阶段。也就是说对象的应用阶段是对象整个生命周期中证明自身“存在价值”的时期。在对象的应用阶段,对象具备下列特征:

◆系统至少维护着对象的一个强引用(Strong Reference);

◆所有对该对象的引用全部是强引用(除非我们显式地使用了:软引用(Soft Reference)、弱引用(Weak Reference)或虚引用(Phantom Reference))。

上面提到了几种不同的引用类型。可能一些读者对这几种引用的概念还不是很清楚,下面分别对之加以介绍。在讲解这几种不同类型的引用之前,我们必须先了解一下Java中对象引用的结构层次。Java对象引用的结构层次示意如图2-6所示。

图2-6 对象引用的结构层次示意

由图2-6我们不难看出,上面所提到的几种引用的层次关系,其中强引用处于顶端,而虚引用则处于底端。下面分别予以介绍。

1.强引用

强引用(Strong Reference)是指JVM内存管理器从根引用集合(Root Set)出发遍寻堆中所有到达对象的路径。当到达某对象的任意路径都不含有引用对象时,对这个对象的引用就被称为强引用。

2.软引用

软引用(Soft Reference)的主要特点是具有较强的引用功能。只有当内存不够的时候,才回收这类内存,因此在内存足够的时候,它们通常不被回收。另外,这些引用对象还能保证在Java抛出OutOfMemory 异常之前,被设置为null。它可以用于实现一些常用资源的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory。再者,软可到达对象的所有软引用都要保证在虚拟机抛出OutOfMemoryError之前已经被清除。否则,清除软引用的时间或者清除不同对象的一组此类引用的顺序将不受任何约束。然而,虚拟机实现不鼓励清除最近访问或使用过的软引用。下面是软引用的实现代码:

软引用技术的引进,使Java应用可以更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃(crash)。因此在处理一些占用内存较大而且声明周期较长,但使用并不频繁的对象时应尽量应用该技术。正像上面的代码一样,我们可以在对象被回收之后重新创建(这里是指那些没有保留运行过程中状态的对象),提高应用对内存的使用效率,提高系统稳定性。但事物总是带有两面性的,有利亦有弊。在某些时候对软引用的使用会降低应用的运行效率与性能,例如:应用软引用的对象的初始化过程较为耗时,或者对象的状态在程序的运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻

烦,有些时候我们要权衡利弊择时应用。

3.弱引用

弱引用(Weak Reference)对象与Soft引用对象的最大不同就在于:GC在进行回收时,需要通过算法检查是否回收Soft引用对象,而对于Weak引用对象,GC总是进行回收。因此Weak引用对象会更容易、更快被GC回收。虽然,GC在运行时一定回收Weak引用对象,但是复杂关系的Weak对象群常常需要好几次GC的运行才能完成。Weak引用对象常常用于Map数据结构中,引用占用内存空间较大的对象,一旦该对象的强引用为null时,

对这个对象引用就不存在了,GC能够快速地回收该对象空间。与软引用类似我们也可以给出相应的应用代码:

弱引用技术主要适用于实现无法防止其键(或值)被回收的规范化映射。另外,弱引用分为“短弱引用(Short Week Reference)”和“长弱引用(Long Week Reference)”,其区别是长弱引用在对象的Finalize方法被GC调用后依然追踪对象。基于安全考虑,不推荐使用长弱引用。因此建议使用下面的方式创建对象的弱引用。

4.虚引用

虚引用(Phantom Reference)的用途较少,主要用于辅助finalize函数的使用。Phantom 对象指一些执行完了finalize函数,并且为不可达对象,但是还没有被GC回收的对象。这种对象可以辅助finalize进行一些后期的回收工作,我们通过覆盖Reference的clear()方法,增强资源回收机制的灵活性。虚引用主要适用于以某种比java 终结机制更灵活的方式调度pre-mortem 清除操作。

&注意在实际程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。

3.1.3不可视阶段

在一个对象经历了应用阶段之后,那么该对象便处于不可视阶段,说明我们在其他区域的代码中已经不可以再引用它,其强引用已经消失,例如,本地变量超出了其可视范围,如下所示。

如果一个对象已使用完,而且在其可视区域不再使用,此时应该主动将其设置为空(null)。可以在上面的代码行obj.doSomething();下添加代码行obj = null;,这样一行代码强制将obj对象置为空值。这样做的意义是,可以帮助JVM及时地发现这个垃圾对象,并且可以及时地回收该对象所占用的系统资源。

3.1.4不可到达阶段

处于不可到达阶段的对象,在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用,这些对象通常是指所有线程栈中的临时变量,所有已装载的类的静态变

量或者对本地代码接口(JNI)的引用。这些对象都是要被垃圾回收器回收的预备对象,但此时该对象并不能被垃圾回收器直接回收。其实所有垃圾回收算法所面临的问题是相同的——找出由分配器分配的,但是用户程序不可到达的内存块。

3.1.5 可收集阶段、终结阶段与释放阶段

对象生命周期的最后一个阶段是可收集阶段、终结阶段与释放阶段。当对象处于这个阶段的时候,可能处于下面三种情况:

(1)垃圾回收器发现该对象已经不可到达。

(2)finalize方法已经被执行。

(3)对象空间已被重用。

当对象处于上面的三种情况时,该对象就处于可收集阶段、终结阶段与释放阶段了。虚拟机就可以直接将该对象回收了。

1.4J ava中数据在内存中是如何存储的

1.4.1 基本数据类型

Java的基本数据类型共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a = 3;long b = 255L;的形式来定义的。如int a = 3;这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值定义在某个程序块里面,程序块退出后,

字段值就消失了),出于追求速度的原因,就存在于栈中。

另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

比如:我们同时定义:

int a = 3;

int b=3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b这个引用变量后,由于在栈中已经有3这个字面值,便将b 直接指向3的地址。这样,就出现了a与b同时均指向3的情况。

定义完a与b的值后,再令a = 4;那么,b不会等于4,还是等于3。在编译器内部,遇到时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。

4.2对象

在Java中,创建一个对象包括对象的声明和实例化两步,下面用一个例题来说明对象的内存模型。假设有类Rectangle定义如下:

class Rectangle{

double width,height;

Rectangle(double w,double h){

width=w;

height=h;

}

}

(1) 声明对象时的内存模型

用Rectangle rect;声明一个对象rect时,将在栈内存为对象的引用变量rect分配内存空间,但Rectangle的值为空,称rect是一个空对象。空对象不能使用,因为它还没有引用任何“实体”。

(2) 对象实例化时的内存模型

当执行rect=new Rectangle(3,5);时,会做两件事:

在堆内存中为类的成员变量width,height分配内存,并将其初始化为各数据类型的默认值;接着进行显式初始化(类定义时的初始化值);最后调用构造方法,为成员变量赋值。

返回堆内存中对象的引用(相当于首地址)给引用变量rect,以后就可以通过rect来引用堆内存中的对象了。

1.5创建多个不同的对象实例

一个类通过使用new运算符可以创建多个不同的对象实例,这些对象实例将在堆中被分配不同的内存空间,改变其中一个对象的状态不会影响其他对象的状态。例如:Rectangle r1=new Rectangle(3,5);

Rectangle r2=new Rectangle(4,6);

此时,将在堆内存中分别为两个对象的成员变量width、height分配内存空间,两个对象在堆内存中占据的空间是互不相同的。如果有:

Rectangle r1=new Rectangle(3,5);

Rectangle r2=r1;

4.4 包装类

基本型别都有对应的包装类:如int对应Integer类,double对应Double类等,基本类型的定义都是直接在栈中,如果用包装类来创建对象,就和普通对象一样了。例如:int i=0;i直接存储在栈中。Integer i(i此时是对象)= new Integer(5);这样,i对象数据存储在堆中,i的引用存储在栈中,通过栈中的引用来操作对象。

4.5 String

String是一个特殊的包装类数据。可以用用以下两种方式创建:

1. String str = new String("abc");

2. String str = "abc";

第一种创建方式,和普通对象的的创建过程一样;

第二种创建方式,Java内部将此语句转化为以下几个步骤:

(1) 先定义一个名为str的对String类的对象引用变量:String str;

(2) 在栈中查找有没有存放值为“abc”的地址,如果没有,则开辟一个存放字面值为“abc”的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为“abc”的地址,则查找对象o,并返回o的地址。

(3) 将str指向对象o的地址。

值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用。

为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。

String str1=“abc”;

String str2=“abc”;

System.out.println(s1==s2);//true

注意,这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。

我们再接着看以下的代码。

String str1=new String(“abc”);

String str2=“abc”;

System.out.println(str1==str2);//false

创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。

以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。

4.6 数组

当定义一个数组,int x[];或int []x;时,在栈内存中创建一个数组引用,通过该引用(即数组名)来引用数组。x=new int[3];将在堆内存中分配3个保存int型数据的空间,堆内存的首地址放到栈内存中,每个数组元素被初始化为0。

4.7静态变量

用static的修饰的变量和方法,实际上是指定了这些变量和方法在内存中的“固定位

置”-static storage,可以理解为所有实例对象共有的内存空间。static变量有点类似于C中的全局变量的概念;静态表示的是内存的共享,就是它的每一个实例都指向同一个内存地址。把static拿来,就是告诉JVM它是静态的,它的引用(含间接引用)都是指向同一个位置,在那个地方,你把它改了,它就不会变成原样,你把它清理了,它就不会回来了。

那静态变量与方法是在什么时候初始化的呢?对于两种不同的类属性,static属性与instance属性,初始化的时机是不同的。instance属性在创建实例的时候初始化,static属性在类加载,也就是第一次用到这个类的时候初始化,对于后来的实例的创建,不再次进行初始化。

我们常可看到类似以下的例子来说明这个问题:

class Student {

static int numberOfStudents=0;

Student() {

numberOfStudents++;

}

}

每一次创建一个新的Student实例时,成员numberOfStudents都会不断的递增,并且所有的Student实例都访问同一个numberOfStudents变量,实际上int numberOfStudents变量在内存中只存储在一个位置上。

1.5 Java的内存管理实例

Java程序的多个部分(方法,变量,对象)驻留在内存中以下两个位置:即堆和栈,现在我们只关心3类事物:实例变量,局部变量和对象:

实例变量和对象驻留在堆上

局部变量驻留在栈上

让我们查看一个java程序,看看他的各部分如何创建并且映射到栈和堆中:

public class Dog {

Collar c;

String name;

//1. main()方法位于栈上

public static void main(String[] args) {

//2. 在栈上创建引用变量d,但Dog对象尚未存在

Dog d;

//3. 创建新的Dog对象,并将其赋予d引用变量

d = new Dog();

//4. 将引用变量的一个副本传递给go()方法

d.go(d);

}

//5. 将go()方法置于栈上,并将dog参数作为局部变量

void go(Dog dog){

//6. 在堆上创建新的Collar对象,并将其赋予Dog的实例变量

c =new Collar();

}

//7.将setName()添加到栈上,并将dogName参数作为其局部变量

void setName(String dogName){

//8. name的实例对象也引用String对象

name=dogName;

}

//9. 程序执行完成后,setName()将会完成并从栈中清除,此时,局部变量dogName也会

消失,尽管它所引用的String仍在堆上

}

1.6垃圾回收机制

(问题一:什么叫垃圾回收机制?)垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用,以免造成内存泄露。

(问题二:java的垃圾回收有什么特点?)JA V A语言不允许程序员直接控制内存空间的使用。内存空间的分配和回收都是由JRE负责在后台自动进行的,尤其是无用内存空间的回收操作(garbagecollection,也称垃圾回收),只能由运行环境提供的一个超级线程进行监测和控制。

(问题三:垃圾回收器什么时候会运行?)一般是在CPU空闲或空间不足时自动进行垃圾回收,而程序员无法精确控制垃圾回收的时机和顺序等。

(问题四:什么样的对象符合垃圾回收条件?)当没有任何获得线程能访问一个对象时,该对象就符合垃圾回收条件。

(问题五:垃圾回收器是怎样工作的?)垃圾回收器如发现一个对象不能被任何活线程访问时,他将认为该对象符合删除条件,就将其加入回收队列,但不是立即销毁对象,何时销毁并释放内存是无法预知的。垃圾回收不能强制执行,然而Java提供了一些方法(如:System.gc()方法),允许你请求JVM执行垃圾回收,而不是要求,虚拟机会尽其所能满足请求,但是不能保证JVM从内存中删除所有不用的对象。

(问题六:一个java程序能够耗尽内存吗?)可以。垃圾收集系统尝试在对象不被使

用时把他们从内存中删除。然而,如果保持太多活的对象,系统则可能会耗尽内存。垃圾回收器不能保证有足够的内存,只能保证可用内存尽可能的得到高效的管理。

(问题七:如何显示的使对象符合垃圾回收条件?)

(1)空引用:当对象没有对他可到达引用时,他就符合垃圾回收的条件。也就是说如果没有对他的引用,删除对象的引用就可以达到目的,因此我们可以把引用变量设置为null,来符合垃圾回收的条件。

Java代码

StringBuffer sb = new StringBuffer("hello");

System.out.println(sb);

sb=null;

(2)重新为引用变量赋值:可以通过设置引用变量引用另一个对象来解除该引用变量与一个对象间的引用关系。

Java代码

StringBuffer sb1 = new StringBuffer("hello");

StringBuffer sb2 = new StringBuffer("goodbye");

System.out.println(sb1);

sb1=sb2;//此时"hello"符合回收条件

(3)方法内创建的对象:所创建的局部变量仅在该方法的作用期间内存在。一旦该方法返回,在这个方法内创建的对象就符合垃圾收集条件。有一种明显的例外情况,就是方法的返回对象。

Java代码

public static void main(String[] args) {

Date d = getDate();

System.out.println("d = " + d);

}

private static Date getDate() {

Date d2 = new Date();

StringBuffer now = new StringBuffer(d2.toString());

System.out.println(now);

return d2;

}

(4)隔离引用:这种情况中,被回收的对象仍具有引用,这种情况称作隔离岛。若存在这两个实例,他们互相引用,并且这两个对象的所有其他引用都删除,其他任何线程无法访问这两个对象中的任意一个。也可以符合垃圾回收条件。

Java代码

public class Island {

Island i;

public static void main(String[] args) {

Island i2 = new Island();

Island i3 = new Island();

Island i4 = new Island();

i2.i=i3;

;

i2=null;

i3=null;

i4=null;

}

}

(问题八:垃圾收集前进行清理------finalize()方法)java提供了一种机制,使你能够在对象刚要被垃圾回收之前运行一些代码。这段代码位于名为finalize()的方法内,所有类从Object类继承这个方法。由于不能保证垃圾回收器会删除某个对象。因此放在finalize()中的代码无法保证运行。因此建议不要重写finalize();

1.7 final问题

final使得被修饰的变量“不变”,但是由于对象型变量的本质是“引用”,使得“不变”也有了两种含义:引用本身的不变?,和引用指向的对象不变?

引用本身的不变:

Java代码

final StringBuffer a=new StringBuffer("immutable");

final StringBuffer b=new StringBuffer("not immutable");

a=b;//编译期错误

引用指向的对象不变:

Java代码

final StringBuffer a=new StringBuffer("immutable");

a.append(" broken!"); //编译通过

可见,final只对引用的“值”(也即它所指向的那个对象的内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化,final是不负责的。这很类似==操作符:==操作符只负责引用的“值”相等,至于这个地址所指向的对象内容是否相等,==操作符是不管的。

在举一个例子:

Java代码

public class Name {

private String firstname;

private String lastname;

public String getFirstname() {

return firstname;

}

public void setFirstname(String firstname) {

this.firstname = firstname;

}

public String getLastname() {

return lastname;

}

public void setLastname(String lastname) {

https://www.doczj.com/doc/a615327380.html,stname = lastname;

}

}

编写测试方法:

java的布局管理

https://www.doczj.com/doc/a615327380.html,/liujun13579/article/details/7772215 java.awt包中大约有 FlowLayout 流式布局 BorderLayout 边框式布局 GridLayout 网格布局 CardLayout 卡片布局 GridBagLayout 复杂的网格布局 javax.swing包中大约有如下布局 BoxLayout 盒式布局 OverlayLayout 重叠布局 ScrollPaneLayout 类JScrollPane使用的布局管理器ViewportLayout 类JViewport使用的布局管理器 详解:

实例:对齐方式 // FlowLayoutDemo.java importjavax.swing.*; importjava.awt.*; public classFlowLayoutDemo extends JFrame { public FlowLayoutDemo() { //设置窗体为流式布局,无参数默认为居中对齐setLayout(new FlowLayout()); //设置窗体中显示的字体样式 setFont(new Font("Helvetica",Font.PLAIN, 14)); //将按钮添加到窗体中

getContentPane().add(newJButton("Button 1")); getContentPane().add(new JButton("Button 2")); getContentPane().add(new JButton("Button3")); getContentPane().add(newJButton("Button 4")); } public static void main(String args[]) { FlowLayoutDemo window = newFlowLayoutDemo(); window.setTitle("流式布局"); //该代码依据放置的组件设定窗口的大小使之正好能容纳你放置的所有组件 window.pack(); window.setVisible(true); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setLocationRelativeTo(null); //让窗体居中显示 } }

Java工程师面试题(三大框架)

Java工程师(程序员)面试题 Struts,Spring,Hibernate三大框架的面试 1.Hibernate工作原理及为什么要用? 原理:1.读取并解析配置文件2.读取并解析映射信息,创建SessionFactory 3.打开Session 4.创建事务Transation 5.持久化操作6.提交事务7.关闭Session 8.关闭SesstionFactory 为什么要用:1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。 2.Hibernate是如何延迟加载? 1. Hibernate2延迟加载实现:a)实体对象b)集合(Collection) 2. Hibernate3 提供了属性的延迟加载功能当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。 3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many 4.Struts1流程: 1、客户端浏览器发出HTTP请求。 2、根据web.xml配置,该请求被ActionServlet接收。 3、根据struts-config.xml配置,ActionServlet先将请求中的参数填充到ActionForm中,然后ActionServlet再将请求发送到Action 进行处理。 4、是否验证,需要验证则调用ActionForm 的validate方法,验证失败则跳转到input,成功则继续。 5、Action从ActionForm获得数据,调用javabean 中的业务方法处理数据。 6、Action返回ActionForward对象,跳转到相应JSP 页面或Action。 7、返回HTTP响应到客户端浏览器。 MVC设计模式:modal:“模型”也称业务逻辑,是正真完成任务的代码,相当与JavaBeanview:视图,其实就是显示界面,相当于JSPcontroller:控制器,他控制模型和视图的交互过程,相当于servletstruts1是基于MVC设计模式hibernate是基于ORM对象关系映射 5.struts是什么? struts1是基于JSP和servlet的一个开源的Web应用框架,使用的是MVC的设计模式struts2是基于webwork技术的框架,是sun和webwork公司联手开发的一个功能非常齐全的框架,struts2和struts1没有任何关系,是一个全新的框架 6.spring是什么? spring是一个集成了许多第三方框架的大杂烩,其核心技术是IOC(控制反转,也称依赖注

Java专业实习总结(精选3篇)

Java专业实习总结(精选3篇) Java专业实习总结 紧张又充实的实习生活又将谢下帷幕,回顾这段时间的实习经历,收获的不仅岁月,还有成长,为此就要认真思考实习总结如何写了。那么如何把实习总结做到重点突出呢?以下是收集整理的Java 专业实习总结,欢迎阅读,希望大家能够喜欢。 Java专业实习总结1 初次涉及Java领域,感觉到Java入门是好像没有C,C++入门快,工具也没有什么TurboC,VisualC++好用,什么JA_HOME,CLASSPATH,虚拟机等概念都是初次基础,旁边的人都很少用Java的。感觉Java就是做Applet的。让我不可思议的是JA2,JDK,J2SE,J2EE,J2ME等新名词在自己的脑海里蔓延。搭起Java开发环境后,记得刚开始还是用UltraEdit编辑并编译的慢慢的改用JCreator了,要开始干项目了,以前从书上看到的东西,在项目中有了很好的机会去温习,开始主要是用Swing,开发桌面系统,放置一个按钮怎么也放不好,后来才知道有一个布局管理器。后来开始涉及到数据库访问,JDBC。随后Java规范了。最开始*的规范是JDBCSpecification,很多概念一目了然,尤其是DATABASE的事务性控制,自己对于她的理解慢慢的有了较为深入的了解。对于开发C/S结构,比如,Swing+JDBC,开发数据库应用系统,让我学会开发两层结构的应用系

统。 开发豆豆网时,基于Linux+JSP+JavaBean+Oracl的系统。不同于Swing+JDBC的开发模式,系统之间多了一层;同时,很多开发技术和面向左面系统不一样,比如分页技术。 完成项目后,自己对于Java的很多方面都比较了解了。开始思考一个问题,J2EE是什么东西?。我们学习Java大概有3个方向,第一,桌面系统,包括C/S结构;第二,J2ME,面向无限领域,很有潜力的家伙,看*的手机用户就知道了。第三,面向企业应用、计算的平台,J2EE。 通过实习,我自身发生了重大的转变,我相信我会在JA开发这条路上走的更长更远。 实习虽然结束了但是给我的感触很大。在信息时代,学习是不断地汲取新信息,获得事业进步的动力。作为一名即将毕业的大学生更应该把学习作为保持工作积极性的重要途径。 实习,是开端也是结束。展现在自己面前的是一片任自己驰骋的沃土,也分明感受到了沉甸甸的责任。在今后的工作和生活中,我将继续学习,深入实践,不断提升自我。 实习的同时也让我了解到了自己的不足,我会继续努力,完善自我。对于学校的精心安排和指导老师的用心辅导非常感谢。 Java专业实习总结2 在经过三年的专业课系统的学习之后,在今年的暑假我迎来了第一次的实习。经过深思熟虑之后,我选择了软件开发的实习与学习。

Java图形用户界面设计

前言 随着Internet的飞速发展,Java技术也得到了越来越广泛的应用。而无论我们是采用J2SE、J2EE还是J2ME,GUI都是不能回避的问题。现在的应用软件越来越要求界面友好、功能强大而又使用简单。而众所周知,在Java中进行GUI 设计相对于其跨平台、多线程等特性的实现要复杂和麻烦许多。这也是很多Java 程序员抱怨的事情。但GUI已经成为程序发展的方向,所以我们也必须了解Java 的GUI设计方法和特点。其实,采用Java提供的布局管理器接口和相应的布局管理类,我们也可以做出相当漂亮的界面来,当然实现起来肯定要比VB麻烦许多。本文试图通过自己的开发经历介绍一些具体的应用实例,希望能给那些曾经象我一样苦闷的Java痴迷者一些帮助。 Java中的布局管理器 2.1 为什么要使用布局 在实际编程中,我们每设计一个窗体,都要往其中添加若干组件。为了管理好这些组件的布局,我们就需要使用布局管理器。比如说,设计一个简单的计算器,或一个文本编辑器等等。这些组件是让JVM 自己任意安排呢?还是按照一定的位置关系进行规范的安排呢?当然应该选择后者。将加入到容器的组件按照一定的顺序和规则放置,使之看起来更美观,这就是布局。在Java中,布局由布局管理器 (LayoutManager) 来管理。那么,我们在什么时候应该使用布局管理器?应选择哪种布局管理器?又该怎样使用布局管理器呢? 如果你写的是GUI程序,在使用AWT/Swing组件时就不应硬性设置组件的大小和位置,而应该使用Java的布局管理器(LayoutManager)来设置和管理可视组件的大小和位置,否则就有可能造成布局混乱。不信,你可以新建一个Frame(或JFrame),通过setBounds()方法往其中添加几个Button(或JButton),一旦你将窗体拉大或缩小时,你会发现组件的排列完全不是按你所预想的那样。为了解决这个问题,即当窗体(或容器)缩放时,组件位置也随之合理调整,我们就需要使用布局管理器。 为此,我们首先要知道Java的布局方式,Java提供的API中有些什么布局管理器,它们的布局特点是什么。 2.2 Java的布局方式 我们都知道,Java的GUI界面定义是由AWT类包和Swing类包来完成的。它在布局管理上采用了容器和布局管理分离的方案。也就是说,容器只管将其他组件放入其中,而不管这些组件是如何放置的。对于布局的管理交给专门的布局管理器类(LayoutManager)来完成。 现在我们来看Java中布局管理器的具体实现。我们前面说过,Java中的容器类(Container),它们只管加入组件(Component),也就是说,它只使用自己的add()方法向自己内部加入组件。同时他记录这些加入其内部的组件的个数,可

JAVA三大框架测试题

框架阶段测试卷 选择题(共50题,每题2分,满分100分) 1.选出不是Restrictions方法的选项(D )。 A.eq() B.gt() C.like() D.isNULL() 2.已知系统中TBL_USER 表对应的实体类是TblUser,下列HQL 语句中正确的是 (D )。 A.from Tbl_User B.select * from tbluser C.select TblUser from TblUser D.from TblUser t where t.uname = "15" 3.阅读下面的代码,要输出查询结果中第一条记录的用户名,正确的代码是(AD )。 String hql = "select u.uname, u.upass from TblUser u"; Query query = session.createQuery(hql); A.Object[] arr = (Object[])query.list().iterator().next(); System.out.println(arr[0]); B.TblUser user = (TblUser)query.list().get(0); System.out.println(user.getUname()); C.String uname = (String)query.list().get(0).get(0); System.out.println(uname); D.String uname = (String)query.list().get(0)[0]; System.out.println(uname); 4.对下面代码中存在的错误,说法不正确的是(D)。 String hql = "from TblUser u where u.status = @status ";//<1> Query query = session.createQuery();//<2> query.setNamedParameter(":status","");//<3> return query.executeQuery(hql);//<4> A.第一行中的命名参数“@status”应该是“:status” B.第二行createQuery 函数应该传入hql 作为参数 C.第三行命名参数名称“:status”应该是“status” D.第四行应该是“return query.list(hql);” 5.下面代码的执行效果是(C )。 String hql = "from TblStudent s order by s.score asc"; Query query = session.createQuery(hql); query.setFirstResult(0); query.setMaxResults(5); return query.list(); A.返回分数最高的五个学生

java实习总结

河北科技师范学院 欧美学院 《JA V A程序设计课程设》 个人实习总结 实习类型教学实习 实习单位欧美学院 指导教师丁亚周 所在院(系)信息技术系 班级 1202 学生姓名于红 学号 9211120214

一、实习时间和地点 时间:2015.3.17-2015.4.17 地点:欧美学院F311,F310 二、实习的内容 (1)本组课题及本人任务; 我们小组设计的是图书管理系统,包括图书信息管理,读者信息管理,管理员信息管理,借阅信息管理,还书信息管理,逾期罚款或损坏赔偿信息管理和数据库。我负责的是图书信息管理,包括对图书信息的查阅,删除,修改和增加。可以满足图书馆的一些日常活动 (2)程序功能简介; 这次实践课我们小组设计的图书管理系统包括了图书信息管理,读者信息管理,管理员信息管理,借阅信息管理,还书信息管理,逾期罚款或损坏赔偿信息管理。主要包含对信息的查找,增加,删除和修改。如下图所示: (3)主体内容(简要说明总体情况,详细介绍本人任务部分): 1.设计分析; 图书管理系统是典型的信息管理系统,其开发主要包括后台数据库的建立前端应用程序的开发两个方面.对于前者要求建立起数据一致性和完整性强、数据安全性好的库.而对于后者则要求应用程序功能完备,易使用等特点.本组结合简单图书馆的要求,设计了数据库结构和应用程序.系统运行结果证明,本文所设计的图书管理系统可以满足图书馆工作人员的需要.

2.程序结构(画流程图) 3.各模块的功能及程序说明; 我所负责的模块是图书信息管理,主要包含四个方面,对图书信息的查找,增加,修改,删除。查找:可以满足图书管理者查询数目的要求,在这个模块,可已使用多种方式查找,包括无条件查询和条件查询,无条件查询是将所有的书一起都找出来,条件查询又包括图书编号查询和模糊条件,这个可以满足图书管理者对具体的一本书查询的要求;增加:按照传统的增加方式进行增加,在新买书时,可以方便图书管理者对数据库进行增加;修改:可以修改图书的名称,适合在录入信息错误时使用;删除:当撤销破旧书目时,可以使用,我所做的所有操作都会对数据库产生影响。 4. 源程序; case 1: System.out.println(" 图书信息: "); System.out.println(" 1. 查询图书信息: "); System.out.println(" 2. 插入图书信息: "); System.out.println(" 3. 删除图书信息: ");

Java三大框架(ssh)总结

Hibernate框架 第一章数据结构 1.1认识数据结构 数据:是信息的载体,是能够被计算机识别、存储、计算的符号集合是计算机处理的对象的总称; 数据元素:也称为结点,是组成数据的基本单位; 数据项:是数据的最小单位; 数据对象:是具有相同特征的数据元素的集合,它是数据的子集; 数据结构:计算机存储、组织数据的方式; ●逻辑结构:指从逻辑关系上描述数据,与数据的存储无关,且独立于语言; ?线性结构:有且仅有一个开始结点和一个终端结点,所有结点最多只有一个前驱 结点和一个直接后继结点; ?非线性结构:指一个结点可能有多个直接前驱和直接后继结点。 ●存储结构:指数据元素及其关系在计算机存储时如何表示,依赖于语言; ●数据运算:通茶昂贵定义在数据的逻辑结构上。 1.2算法 是为求解一个问题需要遵循的,被清晰的制定的简单指令的集合;正确的算法有如下特点: ●用待处理问题的相关信息作为输入数据 ●对一个既定的合法输入,多次执行同一算法,总返回同一个结果(随机算法除外) ●算法中的指令是可行的,即每个指令都可以实现 ●算法中指令的数量是有限的 ●算法执行完毕后,能够输出正确的数据集合 1.3算法分析 目的在于选择合适的算法,算法分析是从复杂度来考虑的。复杂度:衡量一个算法好坏的重要手段; ●时间复杂度:以算法执行时间长短来衡量 ●空间复杂度:以算法执行占用的存储空间来衡量

第二章算法 第三章设计模式 3.1面向对象设计原则 单一职责原则:要求每个对象应该只有一种责任; 开闭原则:设计程序时对扩展开放,对修改关闭; 里氏替换原则:任何情况下,子类替换父类,不会影响程序运行; 依赖倒置原则:提倡高层不依赖底层,二者都依赖抽象; 接口隔离原则:把多个功能分开声明,不强迫客户实现不需要的功能; 迪米特原则:最少只是原则尽可能的降低访问级别; 组合/聚合复用原则:尽量不用继承达到复用类的目的,而是使用组合和聚合。 3.2设计模式分类 创建型模式:如何创建对象以及何时创建对象,工厂模式,单例模式 结构型模式:对象该如何组织以及采用什么样的结构更合理 行为型模式:规定了各个对象应该具备的职责以及对象间的通信模式 3.3什么是框架 应用程序骨架;框架技术的优势在于: ●不用再考虑公共问题,框架已经帮我们做好了 ●可以专心在业务逻辑上,保证核心业务逻辑的开发质量 ●结构统一,便于学习、维护 ●框架集成的前人的经验有助于写出稳健、性能优良并且结构优良的高质量程序 3.4主流框架 3.4.1 Struts框架 最早的Java开源框架之一,定义了通用的Controller(控制器),通过配置文件(一般是struts-config.xml)隔离了Model(模型)和View(视图),以Action的概念对用户请求进行了封装,是代码更清晰易读。 3.4.2 Struts2框架 新的框架特性: ●从逻辑中分离出横切关注点的拦截器 ●减少或者消除配置文件 ●贯穿整个框架的强大表达式语言 ●支持可变更和可重用的基于MVC模式的标签API

JAVA 框架 SPRING 总结

Spring是什么? Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。他提供依赖注入容器,目标是使现有的技术更加易用,促进良好的编程习惯。 Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式 Spring的6大容器 1、核心容器:核心容器提供Spring框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 2、Spring(JEE)上下文:Spring上下文是一个配置文件,向Spring框架提供上下 文信息。Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。 3、Spring AOP:通过配置管理特性,Spring AOP模块直接将面向方面的编程功能集 成到了Spring框架中。所以,可以很容易地使Spring框架管理的任何对象支持AOP。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。 4、Spring DAO:JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管 理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构。 5、Spring ORM:Spring框架插入了若干个ORM框架,从而提供了ORM的对象关 系工具,其中包括JDO、Hibernate和iBatis SQL Map。所有这些都遵从Spring的通用事务和DAO异常层次结构。 6、Spring Web模块:Web上下文模块建立在应用程序上下文模块之上,为基于Web 的应用程序提供了上下文。所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 7、Spring MVC框架:MVC框架是一个全功能的构建Web应用程序的MVC实现。 通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。 Spring框架的功能可以用在任何J2EE服务器中,大多数功能也适用于不受管理的环境。Spring的核心要点是:支持不绑定到特定J2EE服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同J2EE环境(Web或EJB)、独立应用程序、测试环境之间重用。

JAVA实训总结

J A V A程序设计课程实训报告 一、实训目的 知识目标 1.了解图形用户界面的编程思路及方法; 2.了解事件及事件处理机制; 3.掌握常用的图形用户界面组件; 4.掌握容器布局的设置方法及组件的添加方法; 5.掌握常见事件类型及事件处理方法; 能力目标 1.与客户沟通的基本能力; 2.团队协作的基本能力; 3.编程的良好习惯; 4.软件调试和测试的能力; 5.查阅文献的能力; 二、项目设置: 1、实训内容 利用所学Java程序设计语言实现一个图形化的计算器。 2、实训要求 1.程序运行正常无误,系统层次清晰合理; 2.实训内容里的要求必须要全面实现; 3.实训过程中要仔细操作,细心观察,勤于思考,注意记录; 4.实训报告要做到文字通畅、论点正确、论述有据; 5.要求学生在指导教师的指导下,独立完成实训的全部内容; 6.在规定时间内完成实训的全部任务,并按规定格式上交实训报告; 三、实训设备 硬件:个人电脑、 软件:、JDK1.6.0_23 四、实训过程 以上的图表示实训编写的程序没有错误,可以正常的运行

以上的图是运行程序时所显示出来的小小计算机的界面 为了实际的运行一下计算机的功能,此时输入1加2 此时计算机上显示的是数字1和数字2相加的结果,3. 为了实际的运行一下计算机的功能,此时输入数字1乘数字2 此时计算机上显示的是数字1和数字2相乘的结果,2. 因为上述的两个小算数成功的运算出正确的结果所以此时关闭小小简单计算机的界面此时出现的编程图面为: 计算机程序的源码: .*; import .*;,insert); addButton("=",command); addButton("+",command); add(panel,; } privatevoidaddButton(Stringlabel,ActionListenerlistener) { JButtonbutton=newJButton(label); (listener); (button);//按钮监听器类,用于显示 } privateclassInsertActionimplementsActionListener { publicvoidactionPerformed(ActionEventevent) { Stringinput=(); if(start) { (""); start=false;

三大框架原理

ooa(object oriented analysis)面向对象分析 ood(object oriented design)面向对象设计 Oop 面向对象编程 Spring javabean的生命周期 配置初始化调用销毁 Spring 1、spring原理 2、IoC概念:控制权由对象本身转向容器:由容器根据配置文件区创建实例并创建各个实例之间依赖关系。 spring的最大作用ioc/di,将类与类的依赖关系写在配置文件中, 程序在运行时根据配置文件动态加载依赖的类,降低的类与类之间 的藕合度。它的原理是在applicationContext.xml加入bean标记, 在bean标记中通过class属性说明具体类名、通过property标签说明 该类的属性名、通过constructor-args说明构造子的参数。其一切都是 返射,当通过applicationContext.getBean(―id名称‖)得到一个类实例时, 就是以bean标签的类名、属性名、构造子的参数为准,通过反射实例对象, 唤起对象的set方法设置属性值、通过构造子的newInstance实例化得到对象。 正因为spring一切都是反射,反射比直接调用的处理速度慢,所以这也是spring 的一个问题。 spring第二大作用就是aop,其机理来自于代理模式,代理模式 有三个角色分别是通用接口、代理、真实对象 代理、真实对象实现的是同一接口,将真实对象作为 代理的一个属性,向客户端公开的是代理,当客户端 调用代理的方法时,代理找到真实对象,调用真实对象 方法,在调用之前之后提供相关的服务,如事务、安全、 日志。其名词分别是代理、真实对象、装备、关切点、连接点。 2、动态代理:不用写代理类,虚拟机根据真实对象实现的接口产生一个类,通过 类实例化一个动态代理,在实例化动态代理时将真实对象 及装备注入到动态代理中,向客户端公开的是动态代理, 当客户端调用动态代理方法时,动态代理根据类的返射得

java布局(java布局)

java布局(java布局) java布局(java布局) GridBagLayout Free setting component location Before use, set the layout to setLayout (), and the parameter is empty, that is, setLayout (null). Create a layout for the component's (x, y) coordinates, as well as the width and height as parameters. SetBonds (new, Rectangle (int, x, int, y, int, W, int, H)): parameters are coordinates and width, height. The setSize (int, int) sets the size of the component The setLocation (int, int) sets the coordinates of the components Example: Rectangle, re=new, Rectangle (10,10,50,30); Button.setBounds (re); Sequential layout (FlowLayout) Constructor: FlowLayout (): establish the sequence layout manager by default that the components on each row will be centered; FlowLayout (int): Specifies alignment, no arguments, FlowLayout.CENTER, or 1: the components on each row will be centered; arguments FlowLayout.LEFT or 0: left justified; arguments FlowLayout.RIGHT or 2: right aligned.

java反射机制

Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。 那么什么是Java的反射呢? 大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。 Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射。 那么Java反射有什么作用呢? 假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。 Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。 Class类 要正确使用Java反射机制就得使用https://www.doczj.com/doc/a615327380.html,ng.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。 反射API ◆反射API用于反应在当前Java虚拟机中的类、接口或者对象信息 ◆功能 —获取一个对象的类信息. —获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息. —检获属于一个接口的常量和方法声明. —创建一个直到程序运行期间才知道名字的类的实例. —获取并设置一个对象的成员,甚至这个成员的名字是 在程序运行期间才知道. —检测一个在运行期间才知道名字的对象的方法 利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信

JAVA布局管理

JA V A布局管理 一、FlowLayout(流布局管理):其组件的放置规律是从上到下,从左到右依次进行放置。构造方法有下列几种: 1.F lowLayout():创建每行组件居中对齐、组件间距为5个像素单位。 2.F lowLayout(int align):创建指定每行的对齐方式、组件间距为5个像素单位。 align取值表示组件的对齐方式:CENTER(居中对齐),LEFT(左对齐),RIGHT(右对齐)。 二、BorderLayout(边框布局管理):将容器分为上、下、左、右、中五个区域,分别对应North(北区),South(南区),West(西区),East(东区)和Center(中区)。用add(component,index)方法向容器中添加组件,其中第二个参数指明组件位置,其取为:BorderLayout.North,BorderLayout.South,BorderLayout.East,BorderLayout.West,BorderLayout.Center。其构造方法有中下几种: 1.B orderLayout():创建组件间无间距的布局对象。 2.B orderLayout(int hgap,int vgap):创建指定组件间距的布局对象。

三、GridLayout(网格布局管理器):将容器分成尺寸相同 的网格,组件被放在网格的空白处,顺序与流式布局一样。 网格中组件大小相同。其构造方法有下列几种: 1.GridLayout()以每行一列的方式构建一个GridLayout 对象。 2.GridLayout(int row,int columns):根据指定行数和列数 构造一个GridLayout对象,组件间距为0。 3.GridLayout(int row,int columns,int hgap,int,vgap): 根据 指定行数和列数构造一个GridLayout对象,组件间距按指定值设置。 四、CardLayout( 卡片布局管理器):它将组件放在一系 列卡片上,一次只能看到一张卡片,一张卡片只能放一个组件。使用构造方法CardLayout()可以构建CardLayout对象。 组件按添加顺序存放在卡片序列中,使用下列方法将组件添加到容器中: add(Component,component,String name); name是卡片中组件的标识。 为了使组件在使用CardLayout容器中可见,可使用CardLayout对象的下列方法: 1)first(Container container):显示第一张卡片。 2) last(Container container):显示最后一张卡片。

整合SSH三大框架介绍

一.在MyEclipse里先建立一个Web project 的项目,选最新版本的java ee。 二.添加struts2框架支持 1.引入struts2必须得几个jar包,放在WebRoot->WEB-INF->lib 目录下。 2.将WEB应用部署到tomcat服务器上:找到tomacat的安装目录Tomcat6.x\apache-tomcat-6.0.33\conf,打开其中的server.xml文件,在文件末尾上面加入例如 这样的句子,其中path的值为你需要访问网站的上下文,docBase的值为该web项目的WebRoot所在的目录,最后一个readloadable最好选true。 3.在WebRoot->WEB-INF->web.xml中加入struts2的过滤

器将部署好的应用纳入到struts2的管辖范围类,具体代码如下 struts2 org.apache.struts2.dispatcher.ng.filter.StrutsPre pareAndExecuteFilter struts2 /* 4.在web项目的src目录下,建一个struts.xml文件,这里是处理struts整个流程的文件。在其中加入 上面的name随便取,extends绝对不能变。 5.这样以后,启动tomcat服务器看看能不能正常启动,如果正常启动后,在浏览器上访问,http://localhost/上下文/index.jsp看能不能进入,若能进入则表示struts2的框架已经成功加到web项目中了,可以开始下一步了。

java_卡片布局_选项卡窗格

/** * qq登陆界面 * 选项卡窗格 * 面板 * 标签 */ package com.test1; import java.awt.*; import javax.swing.*; public class pp77 extends JFrame{ //北部区域 JLabel jl1;//一个标签 //南部区域 JButton jb1,jb2,jb3; //3个按钮放到一个面板上 JPanel jp1; //中部区域 JTabbedPane jtp;//一个选项卡窗格 JPanel jp2,jp3,jp4;//3个选项卡页 JLabel jl2,jl3,jl4,jl5;//选项卡内标签 //号码输入文本框 JTextField jtf; //登录密码框

JPasswordField jpf; //清除号码的Button JButton jb4; //隐身登陆、记住密码 JCheckBox jcb1,jcb2; public static void main(String[] args) {//主函数 // TODO Auto-generated method stub pp77 op=new pp77(); } public pp77()//构造函数 { jl2=new JLabel("QQ号码",JLabel.CENTER);//标签居中 jl3=new JLabel("QQ密码",JLabel.CENTER); jl4=new JLabel("忘记密码",JLabel.CENTER); //// // jl4.setFont(new Font("宋体",Font.PLAIN,16)); jl4.setForeground(Color.BLUE);//设置字体颜色 // jl5=new JLabel("申请密码保"); jl5.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//定义手型鼠标 // 文本框密码框按钮 jtf=new JTextField(); jpf=new JPasswordField(); jb4=new JButton("清楚密码");

JAVA反射机制(内含大量实例)

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。 反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实

际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素。 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。 二、Java中的类反射: Reflection 是 Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 1.检测类: 1.1 reflection的工作机制 考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。

三十三、Java图形化界面设计——布局管理器之null布局(空布局)

三十三、Java图形化界面设计——布局管理器之null布局(空布局) 一般容器都有默认布局方式,但是有时候需要精确指定各个组建的大小和位置,就需要用到空布局。 操作方法: 1)首先利用setLayout(null)语句将容器的布局设置为null布局(空布局)。 2)再调用组件的setBounds(int x, int y, int width,int height)方法设置组件在容器中的大小和位置,单位均为像素。 x为控件左边缘离窗体左边缘的距离 y为控件上边缘离窗体上边缘的距离 width为控件宽度 height为控件高度 实例:使用空布局精确定位组件的位置 // NullLayoutDemo.java

import java.awt.*; import javax.swing.*; public class NullLayoutDemo{ JFrame fr; JButton a,b; NullLayoutDemo() { fr = new JFrame(); fr.setBounds(100,100,250,150); //设置窗体为空布局 fr.setLayout(null); a=new JButton("按钮a"); b=new JButton("按钮b"); fr.getContentPane().add(a); //设置按钮a的精确位置 a.setBounds(30,30,80,25);

fr.getContentPane().add(b); b.setBounds(150,40,80,25); fr.setTitle("NullLayoutDemo"); fr.setVisible(true); fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fr.setLocationRelativeTo(null); //让窗体居中显示} public static void main(String args[]){ new NullLayoutDemo(); } } 程序运行结果如下:

相关主题
文本预览
相关文档 最新文档