- 浏览: 27156 次
- 性别:
- 来自: 福州
最新评论
问题一:我声明了什么!
String s = "Hello world!";
许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是"Hello world!"。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
这个语句声明的是一个指向对象的引用,名为“s”,可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:
String string = s;
我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。
问题二:"=="和equals方法究竟有什么区别?
==操作符专门用来比较变量的值是否相等。
int a=10;
int b=10;
则a==b将是true。
但:
String a=new String("foo");
String b=new String("foo");
则a==b将返回false。
对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是“两个”,它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。虽然,a和b所指的对象,它们的内容都是"foo",应该是“相等”,但是==操作符并不涉及到对象内容的比较。
对象内容的比较应使用Object对象的equals方法。
boolean equals(Object o){
return this==o;
}
Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。
例如:
Class MyClass{
private String content;
...
boolean equals(Object another){
return true;
}
}
MyClass类中的equals方法覆盖了父类object类的equals方法。这个实现会导致无论MyClass类的实例内容如何,它们之间的比较永远返回true。
所以当使用equals方法判断对象的内容是否相等,请不要想当然。因为可能你认为相等,而这个类的创建者不这样认为,而类的equals方法的实现是由他掌握的。
问题三:String和StringBuffer的区别
String类被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。请看下列代码:
String s = "Hello";
s = s + " world!";
s所指向的对象是否改变了呢?在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
所以,如果经常对字符串进行各种各样的修改,使用String类来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。
问题四:逻辑与/或 和 短路与/或的区别
逻辑操作符:&(与运算),^(异或运算),|(或运算)。
短路逻辑操作符:&&(并且),||(或者).
短路与/或运算符和逻辑与/或一样可以实现逻辑运算,但是此时有一个重要的区别:用逻辑与/或运算时,不管操作符两边的条件表达式成不成立,它都要进行运算判断,而短路与/或运算不一样了,如果通过左侧的操作数就可以进行它们需要的判断,那么它就不会再计算右侧的操作数了,请看下面的例子:
- ......
- double value=0;
- if(value!=0 && 1/value<1000){
- System.out.println("The value is not too small.");
- }
- else{
- System.out.println("The value is too small.");
- }
- ......
......
double value=0;
if(value!=0 && 1/value<1000){
System.out.println("The value is not too small.");
}
else{
System.out.println("The value is too small.");
}
......
运行结果:
The value is too small.
结果分析:
照理说应会出现除数为0的错误,但由于条件逻辑操作符是短路操作符,显然,value!=0条件不成立,立即就可作出判断应执行else后的语句,所以它就不再会运算判断1/value<1000了.如果不懂请再看一例:
- ......
- double int1=0,int2=1,int3=1;
- if(int1!=0 & (int2=2)==1){
- }
- System.out.println("int2="+int2);
- if(int1!=0 && (int3=2)==1){
- }
- System.out.println("int3="+int3);
- ......
......
double int1=0,int2=1,int3=1;
if(int1!=0 & (int2=2)==1){
}
System.out.println("int2="+int2);
if(int1!=0 && (int3=2)==1){
}
System.out.println("int3="+int3);
......
运行结果:
int2=2.0
int3=1.0
问题五:实例变量与类变量(静态变量)
可以通过两种方法在类中存储数据──作为实例变量和类变量.实例变量是特定于对象的,如果你有两个对象(即一个类的两个实例),每一个对象中的实例变量独立于另一个对象中的实例变量的;另一方面,两个对象的类变量均指向相同的数据,并因此面保存相同的值,换句话说,类变量被类中的所有对象共享,类变量在声明时比实例变量多一个static.
- class Data{
- public int intdata=0;//intdata在这儿是实例变量
- }
- public class Test{
- public static void main(String[] args){
- Data a,b;
- a=new Data ();
- b=new Data ();
- a.intdata=1;
- System.out.println("b.indata="+b.intdata);
- }
- }
class Data{
public int intdata=0;//intdata在这儿是实例变量
}
public class Test{
public static void main(String[] args){
Data a,b;
a=new Data ();
b=new Data ();
a.intdata=1;
System.out.println("b.indata="+b.intdata);
}
}
运行结果:
b.intdata=0
结果分析:
可以看出,a.intdata的值虽然变了,但并没有影响b.intdata.
但是如果在Data类中声明intdata时,在其前面加上static就变成类变量了(即:public static int intdata=0;),则此时运行结果会变为:b.intdata=1
这次a.intdata值的改变可把b.intdata影响了,事实上,对象a和b的类变量均指向相同的数据,所有值一样,这就是类变量的作用.
问题六:实例方法,类方法(静态方法),构造器方法
我们通常所说的方法系指实例方法。类方法(即静态方法)与实例方法最大的区别是:在形式上类方法多一个static,在用法上不必创建对象就可直接调用类方法(而实例方法却一定要先创建对象,再通过对象调用)。
- class Add{
- static int addNum(int op1,int op2){
- return op1+op2;
- }
- }
- public class Test{
- public static void main(String[] args){
- //直接用类名作为对象调用类方法
- System.out.println("addem(2,2)="+Add.addNum(2,2));
- }
- }
class Add{
static int addNum(int op1,int op2){
return op1+op2;
}
}
public class Test{
public static void main(String[] args){
//直接用类名作为对象调用类方法
System.out.println("addem(2,2)="+Add.addNum(2,2));
}
}
注: 也可按通常的方法,即先创建对象,再调用方法,不过,这时static就无任何意义了。
构造器方法,它是用来初始化对象中的数据的一种方法,创建很容易,只需在类中加上一个与这个类同名的方法,不需要在前面加任何访问说明符或者返回类型,另外,构造器也一样可以像方法一样传递参数.
- class Data{
- private String data1;//事先声明
- Data(String s){
- data1=s; /*通过接收数据来初始化变量.(注:不能在构造器内声明变量,事先在外就要声明.)*/
- }
- public String getData(){
- return data1;
- }
- }
- public class Test{
- public static void main(String[] args){
- /*通过传递参数调用构造器新建一个对象,再通过对象调用方法得到数据*/
- System.out.println((new Data("I love you")).getData());
- }
- }
class Data{
private String data1;//事先声明
Data(String s){
data1=s; /*通过接收数据来初始化变量.(注:不能在构造器内声明变量,事先在外就要声明.)*/
}
public String getData(){
return data1;
}
}
public class Test{
public static void main(String[] args){
/*通过传递参数调用构造器新建一个对象,再通过对象调用方法得到数据*/
System.out.println((new Data("I love you")).getData());
}
}
问题七:接口与类
类是对一类特定对象的规格说明,我们可以定义类,然后创建类的对象,通过创建类的对象来组合所有属于该类的组件,而接口不能这样做.而接口实质上就是一个常量和抽象方法的集合,要使用一个接口,就需要在类中实现这个接口,然后作为类定义的一部分,编写接口中声明的每一个方法,接口中的方法永远是public,abstract,接口中的常量永远是public static和final,因此不需要为它们说明属性.因为在Java中不支持多重继承,但是,可以用接口来实现类似的功能,这是接口的重要作用之一。
- interface anyone{ //定义一个接口
- final double PI=3.1416;
- void setNumber(int number);
- int getNumber();
- }
interface anyone{ //定义一个接口
final double PI=3.1416;
void setNumber(int number);
int getNumber();
}
interface anyother{ //定义另一个接口
void setString(String str);
String getString();
}
- class Test implement anyone,anyother{ //定义一个类,并使用两个接口
- int number;
- String str;
- public Test(){
- }
- void setNumber(int number){
- this.number=number;
- }
- void setString(String str){
- this.str=str;
- }
- void int getNumber(){
- }//可以为一个空实现.
- void String getString(){
- }
- }
发表评论
-
基础数据结构——图
2010-09-20 15:49 875图(Graph)G由两个 ... -
基础数据结构——树
2010-09-20 15:48 795树:T={K,R}。K是包含n个结点的有穷集合(n ... -
基础数据结构——栈和队列
2010-09-20 15:40 745所谓的栈,是一个含有至少两个基本操作的抽象数据类型 ... -
基本数据结构——数组和链表
2010-09-20 15:38 1182数组的这个可 ... -
集合框架——Map
2010-09-20 15:28 782Map集合为映射 ... -
集合框架——Set
2010-09-20 15:19 823Set集合为集类型,集是最简单的一种集合,存放于集 ... -
集合框架——List
2010-09-20 15:16 1142List集合为列表类型,列表的主要特征是存放其中的 ... -
集合框架——Collection
2010-09-20 15:12 666Collection接口是List接口和Set接口 ... -
Object
2010-09-20 12:09 786java.lang.Object类是所有Java类的最高层次 ... -
堆和栈的区别
2010-09-20 12:06 615栈与堆都是Java用来在Ram中存放数据的地方。 与C++不同 ... -
Comparable和Comparator
2010-09-20 09:22 509public interface Comparable&l ... -
如何使用异常的原则(转)
2010-09-17 15:00 444作者:Bill Venners著,chenkw 译 摘要 ... -
异常的捕获与抛出原则(转)
2010-09-17 14:58 686在可能会出现exception的 ... -
J2EE系统异常的处理准则(转)
2010-09-17 11:43 612J2EE系统异常的处理准则 ... -
J2EE项目的异常处理(转)
2010-09-17 11:18 526为什么要在J2EE项目中谈 ... -
集合框架——简介
2010-09-16 14:46 729一、初识: 集合类是 Java基础技术中十分 ... -
异常那点事
2010-09-16 14:05 604一、概述 在Java程序设计语言中,异常对象都是派生自jav ... -
内部类详解
2010-09-16 13:11 638内部类详解 1、定义 ... -
优化JVM参数提高eclipse运行速度(转)
2010-09-16 12:59 575性能优化从身边做起。 首先建立评估体系,将workspac ... -
四个有害的java编码习惯
2010-09-15 19:16 591John O'Hanley 的这篇文章列举了四个有害的java ...
相关推荐
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
Java基础入门教程 第7章 Java中的异常处理(共26页).ppt Java基础入门教程 第8章 文件流的输入输出操作(共37页).ppt Java基础入门教程 第9章 Java的高级特性(共32页).ppt jdk api 1.7.chm JDK_API_1_6_zh_...
二、 Java语法基础 5 数据类型 5 运算符号 14 语句 15 函数 15 方法重载(Overloadjing)与重写(Overriding) 16 数组 17 总结 18 三、 常见关键字 20 四、 面向对象★★★★★ 21 五、 封装(面向对象特征之一)★...
Java基础思维导图涵盖大部分Java基础重点内容。适用于新手小白理解Java学习之路。
JAVA_7 IO输入输出 JAVA_8 AWT图形界面编程 JFC AWT Swing JAVA_8 AWT图形界面编程 JFC Swing JAVA_9 Applet JAVA_10 线程 JAVA_11 网络程序设计 JAVA_12 JFC Swing JAVA_13 JDBC JAVA_13 JDBC编程
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
JAVA程序设计 第一章 计算机语言概述 第二章 Java的开发环境 ...第七章 Java小应用程序Applet 第八章 用户界面 第九章 Java的多线程机制 第十章 Java网络编程基础 第十一章 Java与数据库的连接—JDBC技术
计算机程序设计(Java)-教案--单元二--Java语言开发基础全文共8页,当前为第1页。计算机程序设计(Java)-教案--单元二--Java语言开发基础全文共8页,当前为第1页。课堂教学计划表 计算机程序设计(Java)-教案--...
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
黑马49期JAVA视频教程【推荐学习】 01-2017javaweb视频教程 ...06-2017java基础+就业班7-12月 07-黑马java32期整套【含两套完整项目】 08.jAVA就业 09.Java夜校视频教程 10.JAVA300集2018版 11.java9新特性
java 实验一 java基础实验 用Java applet和application分别编写一个程序进行10年存款的本息计算。 已知两个二维数组a,b,其初值如下: int a[][]=new int[2][3]; int b[][]={ {1,5,2,8},{5,9,10,-3},{2,7,-5,-18} ...
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
今 年 6月 7日 ,由 SUN公 司 和 台 湾 经 济 事 务 部 信 息 发 展 局, 台湾信 息 技 术 研究 所 等 单 位 牵 头 ,成 立 了 一 个 "Java联 盟 ", 参 加 的 有 22个 在 台 湾相 当 著 名 的 计 算 机公 司 ,并 在 台 ...
完整版精品java课件 Java基础入门教程 Java程序设计 第7章 字符串处理(共38页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第8章 异常处理(共27页).ppt 完整版精品java课件 Java基础入门教程 Java...
某培训公司内部机密资料。 java培训笔记(java基础知识第一到七天) 基础知识部分的知识点。
7 第六章 Java图形与图像处理 8 第七章 多线程与异常处理 9 第八章 数据流(1) 10 第八章 数据流(2) 11 第九章 网络编程 12 第十章 Java数据库连接 13 第十一章 数据结构及算法分析 14 第十二章 J2ME基础
JAVA入门基础篇,适合于初学者.第一章 Java语言入门 授课内容: Java 的诞生 Java 的特点 安装SUN公司的SDK 一个Java程序的开发过程 一个简单的Java应用程序的开发过程 什么是JSP 授课目的: ...
完整版 Java编程基础入门教程 Java语言程序设计 第7章_流和文件(共63页).ppt 完整版 Java编程基础入门教程 Java语言程序设计 第8章_多线程与异常处理(共72页).ppt 完整版 Java编程基础入门教程 Java语言程序设计...
第一部分:Java开发入门 第二部分:Java语法基础 第三部分:Java核心编程 第四部分:Java图形编程 第五部分:Java网络编程