一 面向对象的特征有哪些方面封装抽象多态继承二 java中的异常处理机制的简单原理和应用概念分类面试提示三 内部类定义分类成员内部类局部内部类匿名内部类静态内部类静态方法内的内部类静态内部类作用分类总结四 线程的基本概念线程的基本状态以及状态之间的关系基本概念基本状态生命周期五 堆栈程序运行时的内存分配策略静态的栈式的堆式的不同变量的内存分配机制类变量static修饰的变量实例变量局部变量JVM的堆和栈Java中堆栈的一些特点及比较自动管理栈和堆堆栈的优势和劣势堆栈存储的数据类型基本数据类型存在于栈中存在栈中的数据可以共享字面值的引用与类对象的引用不同包装类数据存在于堆中关于String str abc的内部工作数据类型包装类的值不可修改从堆和栈的功能和作用来通俗的比较
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响. 面向对象的封装性,即将对象封装成一个高度自治和相对封闭的个体,对象状态(属性)由这个对象自己的行为(方法)来读取和改变.
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。要善于划分问题的边界,当前系统需要什么,就只考虑什么。
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。
对象的一个新类可以从现有的类中派生,新类继承了原始类的特性,新类称为原始对象的一个派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。继承性很好的解决了软件的可重用性问题。
异常是指java程序运行时(非编译)所发生的非正常情况或错误,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。 java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。
就按照三个级别去思考:虚拟机必须宕机的错误,程序可以死掉也可以不死掉的错误,程序不应该死掉的错误。
内部类
***成员内部类** * **普通成员内部类(非静态、非接口)** * 修饰符:abstract,final,访问控制符任意 * 成员:不可以包含静态成员(态方法、静态Field、静态初始化块) * 被创建或访问:Outer outer = new Outer();Outer.Inner1 inner1 = outer.new Innner1(); * 访问外部类:所有成员 * **静态内部类** * 修饰符:abstract,final,static,访问控制符任意 * 被创建或访问:外部类名.内部类名(外部引用) * 访问外部类:不静态内部类不能访问外部类的实例成员(需要实例化),只能访问外部类的类成员 * **接口静态内部类** * 对象类型:interface * 修饰符:接口内部类只能是public修饰的静态内部类,并且默认是public static修饰 * 成员:静态变量(public static final),抽象方法(public abstract) * 被创建或访问:外部类名.内部类名(外部引用) * 访问外部类:不静态内部类不能访问外部类的实例成员(需要实例化),只能访问外部类的类成员*局部内部类 * **普通局部内部类** * 修饰符:不能使用访问控制符和static,可以使用final或abstract修饰符 * 成员:不能有静态成员 * 被创建或访问:只能在方法内定义变量、创建实例或派生子类其,他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问 * 访问外部类:可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符 * **匿名内部类** * 对象类型:class,interface * 继承或实现:不能是抽象类,只能继承一个父类,或实现一个接口 * 修饰符:不能使用访问控制符,static,final或abstract修饰符 * 成员:不能有静态成员 ,不能定义构造器 * 被创建或访问:只能在方法内定义变量、创建实例或派生子类其,他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问 * 访问外部类:可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符 * **静态方法中的内部类** * 修饰符:不能在类前面加static关键字 * 访问外部类:了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.
栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java中的数据类型有两种。一种是基本类型(primitivetypes), 共有8种,即int,short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a= 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a= 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),*出于追求速度的原因,就存在于栈中。
Java内部将此语句转化为以下几个步骤:【String str = “abc”,String str不要连着】
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在【栈】中查找有没有存放值为”abc”的地址,如果没有,则开辟一个存放字面值为”abc”的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为”abc”的地址,则查找对象o,并返回o的地址。【上文说数据时存放在堆中,此文说数据存放在栈中】[因为此处不是通过new()创建的啊]
(3)将str指向对象o的地址。
值得注意的是,一般String类中字符串值都是直接存值的。但像String str = “abc”;这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。 String str1=”abc”; String str2=”abc”; System.out.println(str1==str2);//true注意,我们这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。 结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。我们再来更进一步,将以上代码改成: String str1=”abc”; String str2=”abc”; str1=”bcd”; System.out.println(str1+”,”+str2);//bcd,abc System.out.println(str1==str2);//false这就是说,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为”bcd”时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。事实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。再修改原来代码:
String str1=”abc”; String str2=”abc”; str1=”bcd”; String str3=str1; System.out.println(str3);//bcd String str4=”bcd”; System.out.println(str1==str4);//true我们再接着看以下的代码。
String str1 = new String(“abc”); String str2 = “abc”; System.out.println(str1==str2); //falseString str1 = “abc”; String str2 = new String(“abc”); System.out.println(str1==str2); //false 创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。新闻热点
疑难解答