java-基础-对象

基本数据的类型的大小是固定的,4类八种,各个表示大小是固定的,java为了跨平台。
非基本类型的Java对象,其大小是个问题?

    Object ob = new Object(); 

一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任何属性的对象的大小。
4byte+8byte
4byte:Java栈中保存引用的所需要的空间
8byte:Java堆中对象的信息。
因为所有的Java非基本类型的对象都需要默认继承Object对象,因此不论什么样的Java对象,其大小都必须是大于8byte。

    Class NewObject {
    int count;
    boolean flag;
    Object ob;
    } 

其大小为:空对象大小(8byte)+int大小(4byte)+Boolean大小(1byte)+空Object引用的大小(4byte)=17byte。但是因为Java在对对象内存分配时都是以8的整数倍来分,就是内存分为大端和小端,内存对齐的知识,因此大于17byte的最接近8的整数倍的是24,因此此对象的大小为24byte。

基本类型的包装类型的大小

这种包装类型已经成为对象了,因此需要把他们作为对象来看待.包装类型的大小至少是12byte(声明一个空Object至少需要的空间),而且12byte没有包含任何有效信息,同时,因为Java对象大小是8的整数倍,因此一个基本类型包装类的大小至少是16byte。在JDK5.0以后,因为加入了自动类型装换,因此,Java虚拟机会在存储方面进行相应的优化.
值得说明的是,java是可以直接处理基本类型的,但是在有些情况下我们需要将其作为对象来处理,这时就需要将其转化为包装类了.所有的包装类(Wrapper Class)都有共同的方法,他们是:

(1)带有基本值参数并创建包装类对象的构造函数.如可以利用Integer包装类创建对象,Integer obj=new Integer(145);

(2)带有字符串参数并创建包装类对象的构造函数.如new Integer(“-45.36”);

(3)可生成对象基本值的typeValue方法,如obj.intValue();

(4)将字符串转换为基本值的 parseType方法,如Integer.parseInt(args[0]);

(5)生成哈稀表代码的hashCode方法,如obj.hasCode();

(6)对同一个类的两个对象进行比较的equals()方法,如obj1.eauqls(obj2);

(7)生成字符串表示法的toString()方法,如obj.toString().

转换关系:

基本类型——>包装器类
Integer obj=new Integer(145);

包装器类——>基本类型
int num=obj.intValue();

字符串——>包装器类
Integer obj=new Integer(“-45.36”);

包装器类——>字符串包装器类

String str=obj.toString();

字符串——>基本类型
int num=Integer.parseInt(“-45.36”);

基本类型——>字符串包装器类

String str=String.valueOf(5);

自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
自动装包:基本类型自动转为包装类.(int >> Integer)
自动拆包:包装类自动转为基本类型.(Integer >> int)
在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀,现在自动转换机制,解决了我们的问题。

int a = 3;
Collection c = new ArrayList();
c.add(a);//自动转换成Integer.

Integer b = new Integer(2);
c.add(b + 2);

这里Integer先自动转换为int进行加法运算,然后int再次转换为Integer.
一、向上转型与向下转型。

对象类型的转换在Java语言平台中经常遇到,主要包括向上转型与向下转型操作。程序开发人员需要熟练掌握这两个转型的方法以及其中容易出错的地方。如何来了解这两个转型的区别呢?笔者认为,以一个现实的例子作为比喻,可能会更加的容易理解。

如现在有动物、鸟类、燕子三个名词,他们之间有什么关系呢?通常我们都会说,燕子是特殊的鸟类,或者说燕子是鸟类的一种。为此,从对象的定义来看,鸟类就是一个父类,而燕子就是一个子类。或者说,燕子对象就是一个鸟类对象。笔者这里要强调的一点就是,由于燕子是鸟类的一个对象,所以鸟类所具有的特性燕子全部具有。而燕子所具有的特性(如迁徙)则鸟类不一定都具有。在这个例子中,燕子也是一种鸟类。为此可以将燕子的对象堪称是一个鸟类的对象。这种方法在Java语言环境中就叫做“向上转型”。从这个例子中可以看出,向上转型是一个从较抽象类型的类(鸟类)向比较具体的类(燕子)过度。由于具体类(燕子)具有抽象类(鸟类)的全部特性,所以在这个转换过程中是不会有问题的。这就好像一个逻辑判断题说燕子是鸟类的一种,其具有鸟类的全部特性。这个命题至少到现在为止是完全正确的。

但是,在实际工作中,我们还经常会遇到向下转型的情况。也就是说从一个抽象类中(鸟类)引用具体类(燕子)中的对象。也就是说,我们可以说燕子是鸟类的一种。但是现在反过来,如果说鸟类就是燕子,那显然就是以偏概全了,因为燕子并不具有其他鸟类的特性。如鸽子的特性燕子就没有。所以,在应用程序开发中,如果将父类对象赋值给子类的对象,就可能有问题。如果硬要这么做的话,则很有可能发生编译器错误。因为父类对象并不一定是子类的实例。这是什么意思呢?即所说的鸟类(父类对象)并不一定是子类对象(燕子)。因为鸟类对象还有可能是鸽子、白鹭等等。所以,如果将父类对象给子类对象的话,那么就会出现问题。

二、如何实现向下转型?

由于向上转型一般都是安全的,即将一个子类对象直接赋值给父类对象,一般被认为是安全的,如燕子是鸟类在哪里都是成立的。所以在向下转型时不需要采用其他的关键字,我们常常把向下转换叫做隐式转换。但是在这里向上转换是一种不安全的转换方式,如说鸟类就是燕子,这种说法无论在哪里都说不过去。为此默认情况下,进行向下转型时,往往会发生编译器错误。

一般情况下,越是具体的对象所具有的特性越多。如燕子的特性就比鸟类的特性多的多。而越抽象的对象反而具有的特性越少,因为其只具有一些抽象对象的共性特征。在进行向下转型操作时,将特性范围小的对象转换为特性范围大的对象肯定会出现问题。为此在向下转型时,必须确保转换后不会出现问题,即具体对象的特性在抽象对象中也全部具备,只有如此才能够进行转换。而且即使满足这个条件,编译器也不不能够进行隐式转换。而是需要采用关键字进行强制转换。如子类对象名字=(子类名)父类对象名字。如果上面这个语法,就可以实现对象类型的强制转换。

笔者在此强调一遍,在进行向下转型时一定要进行强制转换。即通过子类对象名字=(子类名)父类对象名字进行赋值,而不能够向向上转型那样进行隐式转换。

三、确保向下转型的准确性。

从以上分析中可以看出,向下转型往往被认为是不安全的。当在程序中执行向下转型操作的时候,如果父类对象不是子类对象的实例,就会发生编译器错误。所以在执行向下转型之前要先作一件事情,就是判断父类对象是否为子类对象的实例。也就是说,先要想一想,燕子就是鸟类这个命题是否成立(在某些特定的情况下这个伪命题可能会成立,如燕子的特性与鸟类的特性完全一致)。只有如此,向下转型才不会出现问题。在进行向下转型操作时,将特性范围小的对象转换为特性范围大的对象肯定会出现问题。但是,如果两个转换的对象特性范围一样大的话,可那么就不会有问题了。

在应用程序开发中,往往通过操作符instanceof来完成这个判断。即可以利用这个操作符来判断是否一个雷实现了某个接口,也可以用来判断一个实例对象是否属于一个类。这个操作符的基本格式为:A(某个类的对象引用) instanceo(操作符号) B (某个类的名称)。这个操作符最后返回的是一个布尔值。如果是false的话,则说明A对象不是类B的实例对象。相反,如果返回的值是true的话,则说明对象A是类B的实例对象。

四、向下转型的注意事项。

在进行向下转型时,需要注意以下几方面的内容:

一是要慎用向下转型。由于向下转型容易出问题,为此不到万不得已的时候,最好不用使用向下转型。条条道路通罗马,如果在编程之前,合理规划类,往往可以避免向下转型的发生。只有其他路走不通的情况下,才考虑通过向下转型的技术来解决问题。

二是在进行向下转型的时候,需要做两件事情。一是一定要使用instanceof操作符来判断转型的合法性,即判断父类对象是否为子类对象的实例。这就好像在编写四则运算时,要判断除数不为零一样。这是必须要做的。也是程序员必须要养成的一个习惯。在进行向下转型时,就自然而然会想到需要进行这个判断。只有如此,应用程序的错误才能够降低。而且还能够满足不同的需求。二是需要注意向上转型与向下转型的区别。一般情况下,向上转型往往被认为是安全的,所以在Java语言平台中向上转型采用的是隐式转型。而向下转型由于特性范围大小的不同,为此往往被认为是不安全的。故系统默认情况下进行向下转型时必须采用强制转型的方式。如果不采用强制转型,则即使满足向下转型的条件,其也会发生编译器错误。所以需要切记,向下转型必须要采用强制转型。

三是需要做好备注等注释工作。由于像向下转型等操作是容易出现问题的地方。为此在进行类似的操作时,最好在行注释或者块注释中能够进行说明。这对于后续的维护与代码的升级是很有帮助的。好记性不如烂笔头。如果没有做好相关注释的话,这次可能没有问题,但是下次再代码升级或者其他原因需要调整或者重写原有的代码时,就可能会因为疏忽而导致转型的失败。

最后笔者再次提醒各位程序员,向上转型大家可以放心大胆的用。但是在使用向下转型技术时,大家要慎重,要按部就班(先判断后使用)的进行操作。

对象引用类型分为强引用、软引用、弱引用和虚引用

强引用:
就是我们一般声明对象是时虚拟机生成的引用,强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收
软引用:
软引用一般被做为缓存来使用。与强引用的区别是,软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来决定是否对软引用进行回收。如果剩余内存比较紧张,则虚拟机会回收软引用所引用的空间;如果剩余内存相对富裕,则不会进行回收。换句话说,虚拟机在发生OutOfMemory时,肯定是没有软引用存在的。

弱引用:
弱引用与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。
强引用不用说,我们系统一般在使用时都是用的强引用。而“软引用”和“弱引用”比较少见。他们一般被作为缓存使用,而且一般是在内存大小比较受限的情况下做为缓存。因为如果内存足够大的话,可以直接使用强引用作为缓存即可,同时可控性更高。因而,他们常见的是被使用在桌面应用系统的缓存。

引用类型

StringBuffer str = new StringBuffer("Hello world"); 

首先,new StringBuffer(”Hello world”)在堆里申请了一坨内存,把创建好的StringBuffer对象放进去。

其次,StringBuffer str声明了一个指针。这个指针本身是存储在栈上的(因为语句写在函数中),可以用来指向某个StringBuffer类型的对象。或者换一种说法,这个指针可以用来保存某个StringBuffer对象的地址。

最后,当中这个等于号(赋值符号)把两者关联起来,也就是把刚申请的那一坨内存的地址保存成str的值。

StringBuffer str2 = str;

实际上就是把str的地址复制给str2,记住,是地址的复制,StringBuffer对象本身并没有复制。所以两个指针指向的是同一个
语句“if(str2 == str)”时,只是判断两个指针的值(也就是对象的地址)是否相等,并不是判断被指向的对象是否内容相同。实际上两个指针的值相同,则肯定是指向同一个对象(所以对象内容必定相同)。但是两个内容相同的对象,它们的地址可能不一样(比如克隆出来的多个对象之间,地址就不同)
final常量的问题
final只是修饰指针的值(也就是限定指针保存的地址不能变)。至于该指针指向的对象,内容是否能变,那就管不着了。

final StringBuffer strConst = new StringBuffer();

可以修改它指向的对象的内容, strConst.append(” “);
但是不能修改它的值strConst = null;
传参的问题

System.out.println(str);

可以认为传进函数的是str这个指针,指针说白了就是一个地址的值,说得再白一点,就是个整数。按照这种理解,就是传值的方式。也就是说,参数传递的是指针本身,所以是传值的。
可以认为传进去的是StringBuffer对象,按照这种理解,就是传引用方式了。因为我们确实是把对象的地址(也就是引用)给传了进去。
不论是传引用还是传值,都可以讲得通,关键取决于你是如何看待参数所传递的东西。

时间: 2024-12-17 20:43:02

java-基础-对象的相关文章

Java基础之004-面向对象

Java基础之004-面向对象                                        35岁学习Java 1.1 面向对象概念 1.1.1理解面向对象 1)     面向对象是相对面向过程而言 2)     面向对象和面向过程都是一种思想 3)     面向过程 强调的是功能行为 4)     面向对象 将功能封装进对象,强调具备了功能的对象. 5)     面向对象是基于面向过程的. 1.1.2面向对象的特点 1)     是一种符合人们思考习惯的思想 2)     可

Java基础教程之对象的方法与数据成员_java

在Java基础教程之从Hello World到面向对象一文中,我们初步了解了对象(object).对象中的数据成员表示对象的状态.对象可以执行方法,表示特定的动作. 此外,我们还了解了类(class).同一类的对象属于相同的类型(type).我们可以定义类,并使用该定义来产生对象. 我们进一步深入到对象.了解Java中方法与数据成员的一些细节. 调用同一对象的数据成员 方法可以调用该对象的数据成员.比如下面我们给Human类增加一个getHeight()的方法.该方法返回height数据成员的值

对象-Java基础学习遇见的问题

问题描述 Java基础学习遇见的问题 我是将自定义的对象,存储到了ArrayList集合中,出现下面错误,咋回事啊 多谢各位大神! 解决方案 19行的public拼错了少了b 解决方案二: ArrayList 里面应该加参数吧 ArrayList> list= new ArrayList>();这样定义试试 解决方案三: 黑马程序员 Java基础学习笔记 线程安全问题java基础问题01java基础问题18 解决方案四: 特殊词都带色的,,,拼错了色不对... 解决方案五: 用的什么开发工具啊

java基础问题求指教谢谢

问题描述 java基础问题求指教谢谢 形如 A a=new A();-------------1 a=new A();--------------2 辣么,a到底指的是哪个对象?1还是2? 五楼的说法对么? 解决方案 只用new关键字是为了创建一个对象,你使用了两次new关键字进行创建,会在内存中创建两个A的对象,a是你声明的一个引用,在程序中以最后一次的指向为准,这里是指向最后一个. 解决方案二: new 最后一个对象时,内存又为它分配了新的地址,所以a只想最后一个 解决方案三: a 在最后被

java基础多线程之共享数据

java基础巩固笔记5-多线程之共享数据 线程范围内共享数据 ThreadLocal类 多线程访问共享数据 几种方式 本文主要总结线程共享数据的相关知识,主要包括两方面:一是某个线程内如何共享数据,保证各个线程的数据不交叉:一是多个线程间如何共享数据,保证数据的一致性. 线程范围内共享数据 自己实现的话,是定义一个Map,线程为键,数据为值,表中的每一项即是为每个线程准备的数据,这样在一个线程中数据是一致的. 例子 package com.iot.thread; import java.util

J2ME中需要的Java基础知识

现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成了一些不必要的麻烦,下面将J2ME中用到的和不需要的Java基础知识做一个简单的说明:        J2ME中使用到的Java基础知识: 1.  Java语法基础:包括基本数据类型.关键字.运算符等等 2.  面向对象的思想:类和对象的概念,继承和多态等等. 3.  异常处理 4.  多线程 J2ME中没有用到的Java基础知识: 1. 

Java数据对象技术JDO简介

作为异军突起的新型语言,Java定义了一个标准的运行环境,用户定义的类在其中得到执行.这些用户自定义类的实例代表了真实环境中的数据,包括储存在数据库.文件或某些大型事务处理系统中的数据,而小型系统通常也需要一种在本地负责控制数据存储的机制. 由于数据访问技术在不同的数据源类型中是不一样的,因此对数据进行访问成了给程序开发人员的一种挑战,程序员需要对每一种类型的数据源使用特定的编程接口(API),即必须至少知道两种语言来基于这些数据源开发业务应用:Java语言和由数据源所决定的数据访问语言.这种数

JAVA基础培训(11),方法的Override

Override, 主要是因为父类的功能无法满足需求,我们又不能直接修改父类的情况下 ,我们通过子类重写,来实现新的功能. package Lession11; import java.util.ArrayList; import java.util.List; /** * 老紫竹JAVA基础培训(11),方法的Override.<br> * * * @author 老紫竹 JAVA世纪网(java2000.net) * */ public class Lession11 { public s

JAVA基础培训(10),方法的Overload介绍

今天在项目里做事,中午休息时间,补上这个教程吧.这次我们看看Overload 的内容 . 测试代码 package lession10; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * 老紫竹JAVA基础培训(10),方法的Overload介绍.<br> * 匹配方式为最特殊匹配,或者叫最准确匹配<br> * 如果发现多个都有相同的匹配度,则编译报错. * *

JAVA基础培训(5),IF语句的使用

这一小节,我们看看if语句的用法,最主要是相等的判断.对于数字还有大于小于的 判断. package lession5; /** * 老紫竹JAVA基础培训(5),IF语句的使用.<br> * * @author 老紫竹 JAVA世纪网(java2000.net) * */ public class Lession5 { public static void main(String[] args) { // ---------------------------------------- //