基础一:一切都是对象

概述

OOP-面向对象编程(Object Oriented Programming),在Java中(几乎)一切都是对象。


用引用操作对象

在Java中一切都是被看作为对象,因此可以采用单一固定的语法。

尽管一切都看做对象,但操作的标示符实际上仅仅是对象的一个“引用”(reference)。

如果想操作一个字符串,则可以创建一个String 引用:

String s ;

但是这里创建的仅仅是引用,而不是对象。因此如果要操作s,这会返回错误。这是因为s实际上并没有与任何对象关联.

错误如下所示:

因此一种安全的做法就是:创建一个引用的同时便进行初始化

String s = "abc";

必须由你创建所有对象

一旦创建了一个引用,就希望它能与一个新的对象相关联。

通常使用new操作符来实现这一目的。比如

String s = new String("abc");

存储到什么位置

程序运行时,对象是怎样放置安排的呢? 特别是内存是怎样分配的呢?

其实有五个不同的地方可以存储数据:

名称 说明
寄存器 最快的存储区,位于存储器内部,但是寄存器的数量极其有限,按需分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。
堆栈 位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接支持。堆栈指针向下移动—>分配新的内存,向上移动—>释放内存。这种分配存储的方法效率仅次于寄存器。 一般来讲,引用存放在堆栈中,Java对象并不存储在其中。
一种通用的内存池(也位于RAM中),用于存放所有的Java对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多长时间。 因此在堆里分配存储有很大的灵活性。这种灵活性必须付出相应的代价:比用堆栈进行分配存储需要更多的时间
常量存储 常量值通常存放在程序代码内部,永远不会被改变。
非RAM存储 数据完全存活于程序之外,比如 流对象 和 持久化对象。

特例:基本类型

在程序设计中常用到一系列类型,他们需要特殊对待,可以把他们想象成基本类型。

之所以特殊对待,是因为new将对象存储在“堆”中,故用new创建一个对象–特别是小的、简单的变量,往往不是很有效。

因此,Java采用了和C,C++相同的方法,也就是不用new创建,而是创建一个并非是引用的“自动“变量。 这个变量直接存储”值“,并置于堆栈中,因此更高效。

Java要确定每种基本类型所占存储控件的大小,它们的大小并不像其他语言那样随着机器硬件架构的变化而变化。

基本类型 大小 最小值 最大值 包装类型
boolean Boolean
char 16-bit Unicode 0 Unicode 2^16-1 Character
byte 8-bits -128 +127 Byte
short 16-bits -2^15 +2^15-1 Short
int 32-bits -2^31 +2^31-1 Integer
long 64-bits -2^63 +2^63-1 Long
float 32-bits IEEE754 IEEE754 Float
double 64-bits IEEE754 IEEE754 Double
void Void

基本类型具有的包装器类,使得可以在堆中创建一个非基本的对象,用来表示对应的基本类型。比如:

char c = ‘x‘;
Character ch = new Character(c);
或者:
Character ch  = new Character(‘x‘);

Java SE5的自动包装功能自动的将基本类型转换为包装器类型

Character ch = ‘x‘;

并可以反向转换:

char c = ch;

高精度数字:

Java提供了2个高精度计算的类

BigInteger BigDecimal.

虽然他们大体上属于包装器类的范畴,但是却没有对应的基本类型。

  • 这两个类都有自己的一系列方法,类似于我们针对主类型执行的操作,也就是说能用 int 或float 做的事情,用BigInteger和BigDecimal 一样可以做,只是必须换用方法调用,而不是使用运算符。此外由于牵涉更多,所以运算速度会慢一点总之我们牺牲了速度,但换来了精度。
  • BigInteger支持任意精度的整数,也就是说我们可精确表示任意大小的整数值;同时在运算过程中不会丢失任何信息;
  • 在BigInteger类中有所有的基本算术运算方法,如加、减、乘、除,以及可能会用到的位运算如或、异或、非、左移、右移等。
  • 从数值上比较两个 BigDecimal 值时,应该使用 compareTo() 而不是 equals()。
  • 要小心使用 BigDecimal(double) 构造函数, 因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。
  • 由于 BigDecimal 对象是不可变的,这些方法中的每一个都会产生新的 BigDecimal 对象。因此,因为创建对象的开销,BigDecimal 不适合于大量的数学计算,但设计它的目的是用来精确地表示小数。如果您正在寻找一种能精确表示如货币量这样的数值,则 BigDecimal 可以很好地胜任该任务。

永远不需要销毁对象

作用域

作用域由花括号的位置决定。


        {
            // x available
            int x = 12 ;
            System.out.println("x:" + x );
            {
                // Both x & y available
                int y = 9 ;
                System.out.println("x:" + x + ",y:" + y);
            }
            // only x available
            System.out.println("x:" + x );
        }

在作用域中定义的变量只可用于作用域结束之前。

对象的作用域

Java对象不具备和基本类型一样的生命周期。

当使用new创建一个java对象时,它可以存活于作用域之外。

比如

{
    String s = new String("sss");
}// end of scope

引用s在作用域终点就消失了,但是s指向的对象任然占据这内存空间。

我们无法在这个作用域之后访问这个对象,因为对它唯一的引用已经超出了作用域的范围。

事实证明,由new创建的对象,只要你需要就会一直保留下去。

那java如何防止这些对象填满内存空间,进而阻塞你的程序呢?

Java中有一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会被再引用的对象。随后,释放这些对象占用的内存空间,以便提供给其他新的对象使用。


创建新的数据类型:类

如果一切都是对象,那什么决定了某一类对象的外观和行为呢? 换句话说 什么确定了对象的类型?

在Java中使用class这个关键字

class ATypeName {
    // class body gose here
}

实例化

ATypeName  a = new ATypeName();

字段和方法

一旦定义了一个类,就可以在类中设置两种类型的元素:字段+方法。

字段可以是任何类型的对象,可以通过起引用与其进行通信;也可以是基本类型中的一种。

如果字段是某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象相关联。

每个对象都有用来存储其字段的空间; 普通字段不能在对象间共享。

    class  DataOnly{
            int i ;
            double d ;
            boolean b ;
        }

尽管这个类除了存储数据之外什么也不能做,但是依然可以创建它的一个对象:

DataOnly data = new DataOnly();

可以给字段赋值,但首先必须知道如何引用一个对象的成员:

objectReference.member

例如:

data.i = 10;
data.d = 1.1;
data.b = false;

基本成员默认值

若类的某个成员是基本类型数据,即使没有初始化,Java会确保它有一个默认值。

当变量作为类的成员变量使用时,Java才确保给定其默认值,以确保那些是基本类型的成员变量得到初始化,防止产生程序错误。

不过最好明确的对变量进行初始化。

上述确保初始化的方法并不适用于“局部变量”(即并非某个类的字段)。

如下:

某个方法中定义

int x ;

这是不会被自动化初始为0 ,如果未明确的赋值,在编译时会抛出异常

方法、参数和返回值

Java的方法决定了一个对象能接收什么样的的消息。 参数列表给出了要传给方法的信息的类型和名称。 方法名和参数列表唯一的标识出某个方法。

Java中的方法只能作为类的一部分创建。 方法只能通过对象才能被调用(static方法是针对类调用的,并不依赖于对象的存在),且这个对象必须能执行这个方法的调用。

如下:

objectName.methodName(arg1,arg2,arg3);

参数列表

像java中任何传递对象的场合一样,这里传递的实际上也是引用(对于基本类型是一个类外。通常尽管传递的是对象,而实际上传递的对象的引用。)

并且引用的类型必须正确。

比如 参数类型为String ,则必须传递一个String对象,否则编译器抛出异常。

假设某个方法接收String为其参数,具体定义如下,该方法必须置于某个类的定义内才能被正确的编译。

int storage(String s){
    return s.length();
}

通过上面的例子,我们还可以了解到return关键字的用法。

  • 代表已经执行完毕,离开此方法
  • 如果该方法有返回值,需要放到return后
boolean flag(){ return true;}
double naturalLogBase(){ return 2.879;}

void nothing(){return ;}
void nothing2(){}

若返回类型是void ,return关键字的作用只是用来退出方法。因此没有必要到方法结束时才离开,可以在任何地方离开。

但如果返回类型不是void ,无论在何处返回,编译器都会强制返回一个正确类型的返回值。


static关键字

通常来说,当创建一个类时,就是在描述那个类的对象的外观与行为。

除非用new创建那个类的对象,否则,实际上并没有获取到任何对象, 执行new 来创建对象时,数据存储空间才能被分配,其方法才能被外界调用。

有两种情况是以上方法无法解决的:

1. 只想为某特定域分配单一存储空间,而不考虑究竟要创建多少对象,甚至根本就不创建对象。

2. 第二种情况是:希望某个方法不与包含它的类的任何对象关联在一起,也就是说,即使没有创建对象,也能够调用该方法。

通过static关键字可以满足这两方面的需求。

当声明一个事物是static时,也就意味着这个域或者方法不会与包含它的那个类的任何对象实例关联子啊一起, 所以即使从未创建某个类的任何对象,也可以通过调用其static方法或者访问其static域。

通常你必须创建一个对象,并且用它来访问数据或者方法,因为非static域和方法必须知道他们一起运作的特定对象。

只需要将static关键字放在定义之前,就可以将字段或者方法设定为static

例如

class StaticTest{
    static int i = 5;
}

即使我们创立了两个StaticTest对象,StaticTest.i也只有一份存储空间,这两个对象共享同一个i.

在这里 a.i和b.i都指向同一个存储空间。

引用static变量的两种方法:

  1. 可以通过一个对象去引用它,比如 上面中的 a.i
  2. 也可以通过类名直接引用,而这对于非静态成员则不行,比如Demo21.i == Demo21.i 这种方式是首选方式,推荐使用这种方式。

类似逻辑同样也适用于 静态方法。

时间: 2024-11-02 12:24:27

基础一:一切都是对象的相关文章

java基础 第2章 一切都是对象

第2章 一切都是对象 "尽管以C++为基础,但Java是一种更纯粹的面向对象程序设计语言". 无论C++还是Java都属于杂合语言.但在Java中,设计者觉得这种杂合并不象在C++里那么重要.杂合语言允许采用多种编程风格:之所以说C++是一种杂合语言,是因为它支持与C语言的向后兼容能力.由于C++是C的一个超集,所以包含的许多特性都是后者不具备的,这些特性使C++在某些地方显得过于复杂. Java语言首先便假定了我们只希望进行面向对象的程序设计.也就是说,正式用它设计之前,必须先将自己

o'c基础第一天类与对象

1. 在代码中如何使用面向对象的思维去解决问题. a. 千万不要自己去1步步实现. b. 先找1下有没有现成的专门做这个事情的人. 框架. 如果框架中有这样的人 直接喊过来用就可以了. c. 框架中如果没有呢?  就自己造1个拥有这个功能的人. 这个人不仅在这个地方可以使用 在另外的地方也可以使用. 2. 面向对象相对于面向过程. 面向对象的优点: 后期程序的维护和扩展非常的方便. 如果功能发生变化 我们只需要换1个人就可以了. OC Swift Java C# ...... 面向过程优点: 与

这些基础知识你都了解吗?——《松本行弘的程序世界》读书笔记(上)

1. 前言 半个月之前买了这本书,还是经园子里的一位网友推荐的.到现在看了一半多,基础的都看完了,剩下的几章可做高级部分来看.这本书看到现在,可以说感触很深,必须做一次读书笔记! 关于这本书,不了解的可以去网上查查.作者是Ruby语言的创始人,可谓是程序世界中的高手,开卷有益,不管你是哪个层次的编程人员,相信都能或多或少的汲取到你想要的营养. 下面将总结一下看完本书我记录下的一些知识点.有的是书中的原话,有的是我个人的理解,供参考. 2. 面向对象 2.1 多态性 面向对象三大原则:继承.封装和

Java千百问_08JDK详解(004)_jdk基础扩展类库都有什么

1.jdk基础扩展类库都有什么 了解java核心框架看这里:java核心框架是什么样的 jdk基础类库分为两大部分,基础库.扩展基础库,提供了相当大量的功能,扩展基础库具体如下: I/O工具(I/O) java.io和java.nio包提供了一组非常丰富的api来管理应用程序的I/O(输入/输出).包括文件和设备I/O.对象序列化.缓冲区管理.字符集支持等.此外,API还为服务端提供了包括多路复用.非阻塞I/O.内存映射和文件锁等功能. 了解更多java.io和java.nio包看这里:[io包

Java编程思想(一)——一切都是对象

<Java编程思想> 作者:Bruce Eckel 虽然这本书是经典,但是对于一个入门java,又没有其他编程经验的人来讲,实在难以看懂,前前后后看了三遍. 第一次什么都不懂的时候硬着头皮看,没看完,看了前面忘了后面,中间很多看不懂.第二次的时候,看懂了很多,但是不知道经典在何处. 第三次,是自己用了这门语言一年后,知道所谓的经典是什么,java的特性都在这里,这书不是从基础的JDK怎么装开始讲起.,大部头的一本书,现代人的话很少去翻了,其实可以当参考书,看哪一部分忘了,直接温故即可.一次在学

在JS中,一切东东其实都是对象

对象是组成JavaScript的基本单元,在JS中,一切东东其实都是对象,而且功能非常强大,它不仅风格独特,功能也与众不同. 一.引用(reference) 引用的概念是JS的基础之一,它是指向对象实际位置的指针.见下面的例子: var items = new Array("abc","def","hig"); //创建此数组的引用 var Ref = items; items.push("klm"); alert(Ref.l

【Java编程思想】二、一切都是对象

尽管Java是基于C++的,但是相比之下,Java是一种更“纯粹”的面向对象设计语言. 2.1 用引用操纵对象 一切都被视为对象, 因此可采用单一固定的语法.尽管一切都被看作对象,但操纵的标识符实际上是对象的一个“引用”. Java里的“引用”与C++中的“引用”是有区别的,但是这个概念不需要完全明白,学会处理引用就可以了. 2.2 必须由你创建所有对象 new关键字的意思就是“给我一个新对象”! 2.2.1对象存储到什么地方 1)寄存器 2)堆栈(RAM) 3)堆(RAM) 4)常量存储(RO

java基础复习之对于String对象,可以使用“=”赋值,也可以使用new关键字赋值,两种方式有什么区别?

String类型是实际工作中经常用到的类型,从数据类型上划分,String是一个引用类型,是API中定义的一个类.所以String类型的对象可以用new创建,例如String name=new String("string");为变量name进行赋值,值为"string" ,然而String类比其他类有些特殊,可以使用'='直接赋值,如 String name="string";也是为变量name进行赋值,值为"string"

《 Java 编程思想》CH02 一切都是对象

尽管Java中一切都看作为对象,但是操纵的标识符实际上对象的一个“引用”. String s; // 这里只是创建了一个引用,而不是一个对象 String s = new String("abcd"); // 使用`new`操作符来创建一个对象,并将其与一个引用相关联 String s = "abcd"; // 字符串可以直接用带引号的文本初始化 必须由你创建所有对象 使用 new 操作符创建一个对象 存储到什么位置 由五个地方可以存储数据: 寄存器:由于寄存器数量