• 01—为什么使用java


    Java解决的问题

    1.指针问题

         java里面没有指针,用引用解决指针问题,但是引用是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象

    引用地址:http://blog.csdn.net/cewei711/article/details/52881139

    Java的对象类型

    在这里,我不泛谈程序语言原理方面的知识,如何为引用,何为指针。只以C++的对象类型为蓝本,讨论C++中对象类型与Java对象类型的异同。

    C++的对象类型分为三种:对象变量,对象指针和对象引用(这里特指是C++的引用)。对象变量,与基本数据类型变量一样,分配在栈中,对象在栈的生命空间结束后,系统会自动释放对象所占用的空间;对象指针,与C语言中的指针一样,都是一个地址,它指向栈中或堆中的一个对象。对象引用是C++中与C不同之外,形象地说,引用就是一个别名,定义引用的时候必须一起初始化,不能引用不存在的对象。下面是C++中定义三种对象类型的代码:

    String a(“string a”);//定义一个String对象指针,它指向对象a(栈对象)

    String *pA = &a;//定义一个String对象指针,它指向对象a(栈对象)

    String *pB = new String(“string b”);//定义一个String对象指针,不过它指向一个分配在堆中的对象

    String &c = a;//定义一个String对象的引用c,它引用a,也即是说c是a的别名,即同一个变量,两个不同的名字而已。只要改变a或c,该变量内容都会发生改变的。

    Java中的对象类型只有一种,那就是引用(注意是Java的引用,而非C++的引用)。下面是定义一个引用的代码。

    String s = new String(“string”);

    在执行此代码时,在内存空间生成的结构如下面所示:

    +--------+              +-------------------------+

           |引用s |--------------------à|对象内容为“string”|

       +-------- +              +-------------------------+

       上面的语句中其实做了两件事情,在堆中创建了一个String对象,内容为”string”,在栈中创建了一个引用s,它指向堆中刚创建好的String对象。并且引用s值的改变不影响它所指的对象,只有通过它调用对象的方法对可能改变对象的内容。请看如下语句:

    s = new String(“abc”);

    在上面这个语句中,只改变s的值,因此不会对内容为”string”对象造成影响(不考虑垃圾回收情况)。只不过是s指向堆中的新对象而已,从指针上来说,就是s的值改变了而已。

    从上面来看,Java的引用,并不与C++的引用相同,因此它不是一个别名;与对象变量也不同,它只是表示一个内存位置,该位置就是存在一个对象的位置,而不是真实的对象变量。并且从指针的意义角度来说,C/C++的指针与Java的引用却是不谋而合。它们都表是一个内存地址,都可以通过这个内存地址来操纵它所对应的对象。因此Java的引用更像C++中的指针,在下文中把它称为Java中的指针,同样也可称为Java中的引用。

    Java中的指针与C++中的指针

    本文开始提到Java中的指针是限制的指针,那么在这里分析Java中的指针可以执行什么运算符。

    在C++的对象指针里面,出现的指针运算符主要有以下几个:*,->。

    运算符*是返回指针所指向的对象,而->是返回指针所指向对象的数据成员或方法成员。由于不存在对象变量,而是通过指针来访问对象的,因此Java中不需要提供*运算符,这是Java优化了C++的一个指针问题。对于->运行符,Java的指针是提供的,不过是采用.运算符的方式提供,看起来与C++中对象变量的.运算符一样,其实意义是有不一样的地方。

    如String s = new String(“abc”);

    s.indexOf(“a”);

           与下面C++代码等价的

           String *s = new String(“abc”);

           s->indexOf(“a”);

      

           对于C++中对象变量出现的复制构造函数,“=”运算符以及“==”运算符问题同样在Java中出现。

       在C++中,如果类没有定义它的“=”运算符,那么有可能会出现浅度复制,而非深度复制,Java也有类似的问题。两者要程序员采用深度复制的策略编写构造函数;如果C++中的对象没有定义“==”运算法,那么它会依次对两个变量比较它的数据成员,看是否都相等。如果定义则按用户的比较方式进行比较。在Java,Object对象定义了equals方法,这个方法是用来比较两个对象如果相等的,Object中的equals方法只是比较两个指针的值是否相等而已,要根据所指向的对象内容进行比较,那应重写该类的equals方法。

           正因为Java中存在指针,所以使用Java同样能写出丰富的数据结构,java中的集合框架就是最好的例子。

           上面只要谈到Java中指针与C++中指针相同或类似的部分,我觉得两者之间是有差别的,差别主要有三个。

           C++中的指针是可以参与和整数的加减运算的,当一个指对指向一个对象数组时,可以通过自增操作符访问该数组的所有元素;并且两个指针能进行减运算,表示两个指表所指向内存的“距离”。而Java的指针是不能参与整数运算和减法运算的。

           C++中的指针是通过new运算或对象变量取地址再进行赋值而初始化的,可以指向堆中或栈中的内存空间。Java同样是类似的,通new运算得到初始化。Java中指针只能是指向堆中的对象,对象只能生存在堆中。C语言是可以通过远指针来指向任意内存的地址,因而可以该问任意内存地址(可能会造成非法访存);Java中的指针向的内存是由JVM来分配的中,由于new运算来实现,不能随所欲为地指向任意内存。

           C++中通过delete和delete[] 运算符进行释放堆中创建的对象。如果对象生存周期完结束,但没有进行内存释放,会出现内存泄露现象。在Java中,程序员不用显式地释放对象,垃圾回收器会管理对象的释放问题,不用程序员担心。Java使用了垃圾回收机制使得程序不用再管理复杂的内存机制,使软件出现内存泄露的情况减少到最低。即Java的引用不用关心内存回收的问题。

          

    小结

           通过上面的分析,我们可以得到这样的结论:Java中的引用与C++中的引用是不同的,并且Java中的引用更像C++中的指针。因此,可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。除了Java外,就本文开头提到的C#以及VB.NET中出现的引用,都类似于C++中的指针。Java中的采用引用的说法,其实是想程序员忘记指针所带来的痛苦;Java的引用比C++中的指针好用得多了,也容易管理,同时提供内存管理机制,让大家用得安心,写得放心而已。
     
     
     

    2.内存泄露

    http://www.importnew.com/12961.html

    Java语言的一个关键的优势就是它的内存管理机制。你只管创建对象,Java的垃圾回收器帮你分配以及回收内存。然而,实际的情况并没有那么简单,因为内存泄漏在Java应用程序中还是时有发生的。

    下面就解释下什么是内存泄漏,它为什么会发生,以及我们如何阻止它的发生。

    1. 什么是内存泄漏?

    内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着。

    要想理解这个定义,我们需要先了解一下对象在内存中的状态。下面的这张图就解释了什么是无用对象以及什么是未被引用对象

    Unused and Unreferenced

    上面图中可以看出,里面有被引用对象和未被引用对象。未被引用对象会被垃圾回收器回收,而被引用的对象却不会。未被引用的对象当然是不再被使用的对象,因为没有对象再引用它。然而无用对象却不全是未被引用对象。其中还有被引用的。就是这种情况导致了内存泄漏。

    2. 为什么会发生内存泄漏?

    来先看看下面的例子,为什么会发生内存泄漏。下面这个例子中,A对象引用B对象,A对象的生命周期(t1-t4)比B对象的生命周期(t2-t3)长的多。当B对象没有被应用程序使用之后,A对象仍然在引用着B对象。这样,垃圾回收器就没办法将B对象从内存中移除,从而导致内存问题,因为如果A引用更多这样的对象,那将有更多的未被引用对象存在,并消耗内存空间。

    B对象也可能会持有许多其他的对象,那这些对象同样也不会被垃圾回收器回收。所有这些没在使用的对象将持续的消耗之前分配的内存空间。

    Object-Life-Time

    3. 如何防止内存泄漏的发生?

    下面是几条容易上手的建议,来帮助你防止内存泄漏的发生。

    • 特别注意一些像HashMap、ArrayList的集合对象,它们经常会引发内存泄漏。当它们被声明为static时,它们的生命周期就会和应用程序一样长。
    • 特别注意事件监听和回调函数。当一个监听器在使用的时候被注册,但不再使用之后却未被反注册。
    • “如果一个类自己管理内存,那开发人员就得小心内存泄漏问题了。” 通常一些成员变量引用其他对象,初始化的时候需要置空。

    3.异常处理

    http://blog.csdn.net/hguisu/article/details/6155636/

     

  • 相关阅读:
    Oracle等待事件Enqueue CI:Cross Instance Call Invocation
    Exadata. Are you ready?
    Beyond the Mobile Goldrush
    推荐一款性能诊断工具Membai
    Does LGWR use synchronous IO even AIO enabled?
    Raid Level,该如何为Oracle存储选择才好?
    Oracle备份恢复:Rman Backup缓慢问题一例
    Usage and Configuration of the Oracle shared Server
    UserManaged Backups
    Oracle Recovery Manager Overview and Configuration
  • 原文地址:https://www.cnblogs.com/brucekun/p/7573067.html
Copyright © 2020-2023  润新知