● Java中, System是什么,out和in是什么?
在Java编程中,我们常常用System.out.println()方法来输出字符串,也许我们都已经猜到println()是方法名,但System是什么,out又是什么呢?
这里就涉及用到一个static关键字。如下图,其实System是java.lang里面的一个类。 out是java.io.PrintStream类的对象。 而out就是System里面的一个数据成员(也称为字段),但这个成员不是基本类,而是java.io.PrintStream类的对象,java.io.PrintStream类有些什么方法等一下再说。我们先看看下面的截图,被关键字static修饰的数据成员或方法可以直接通过"类名.数据成员"或"类名.方法"来引用,而无须先建立对象(C++中也是这样)。所以System.out是应用了out这个静态数据成员。 |
System.in System.in是一个很原始、很简陋的输入流对象,通常不直接使用它来读取用户的输入。 |
● Java中,一切皆是对象
虽然Java的数据类型分为:基本数据类型与对象(object)类型, 但基本数据类型也有其包装类. 例如java中基本的类型,int包装类是 Integer; 基本数据类型和它所对应的包装类类型可以相互直接赋值, 例如: int num = 5; Integer i = num;//这时候等价于 Integer i = new Integer(num); 同样: Integer num = new Integer(3); int i = num;//这时候相当于 int i = num.intValue(); 也就是说int类型和Integer可以直接相互赋值 例如Integer i = 5; 这也导致了一个很难理解的问题: public static void test(Object obj){} 这样的方法直接使用int类型的参数的时候是可以编译通过的,但是在这里相当于传入的是Integer对象,而不是证明int类型是Object类型. |
● Java中的常用包
Java采用包结构来组织和管理类和接口文件。本文介绍Java语言类库中几个常用的包,因为这几个包在软件开发与应用中经常需要用到,其中有些包是必要的。若是离开它,还真不能做事情了。
第一个包:java.lang包。 该包提供了Java语言进行程序设计的基础类,它是默认导入的包。该包里面的Runnable接口和Object、Math、String、StringBuffer、System、Thread以及Throwable类需要重点掌握,因为它们应用很广。 第二个包:java.util包。 该包提供了包含集合框架、遗留的集合类、事件模型、日期和时间实施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。
第三个包:java.io包。 该包通过文件系统、数据流和序列化提供系统的输入与输出。
第四个包:java.net包。 该包提供实现网络应用与开发的类。
第五个包:java.sql包。 该包提供了使用Java语言访问并处理存储在数据源(通常是一个关系型数据库)中的数据API。
第六个包:java.awt包 第七个包:javax.swing包。 这两个包提供了GUI设计与开发的类。java.awt包提供了创建界面和绘制图形图像的所有类,而javax.swing包提供了一组"轻量级"的组件,尽量让这些组件在所有平台上的工作方式相同。
第八个包:java.text包。 提供了与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。
关于上述这些包结构,除了第一个包是自动导入外,其余的包都需要使用import语句导入,才可使用其包里面的类与接口。若想深入了解它们,请多阅读JDKAPI文档,同时,多使用这些包里的类与接口来解决问题和满足需求。
总结: 1)Java语言采用包结构组织和管理类与接口,避免命名冲突,结构富有条理而清晰。 2)关注上述常用包,实则是掌握这些包结构下的类与接口的应用。利用它们,加上创意,设计和造就一个个"产品"。
注意: import java.util.*; *表示这个包下的所有类库(不包括子包) |
● Scanner的用法
①建立一个scanner对象;②调用scanner这个对象的函数, 如nextLine(); //返回Enter键之前的所有字符, 并赋值给相关变量;③打印出这个变量或对之进行其它操作 |
●字面常量 (字面量, literal)
字面常量就是一个确定的值本身. 有名常量,即是把常量 赋给这个名字
int a= 1 1是字面量 然后这个字面量有个名字a,就是有名常量 |
Java的字面常量有三种类型:基本类型的字面量、字符串字面量以及null字面量。 |
● 代码对齐快捷键
Eclipse: 选中, ctrl + shift + f |
对比: VC++: 选中, alt+f8 Pycharm: 选中, ctrl+alt+l |
● Java如何读入一个字符
Java的Scanner类中没有nextChar()这种方法(可能有原因, 尚未知); 可用如下方法读入一个字符: next().charAt(0)//这里是连续用了两个Scanner类的方法 // Scanner类的next方法是返回扫描器(输入流)中的下一个标记,它是一个String对象。 String类有一个charAt方法,它返回String对象中指定索引处的字符,传递索引0,表示字符串中的第一个字符。 这样写并不麻烦,用用就习惯了。 |
● 如何限定数组的大小呢?
JAVA中,数组不允许在方括号中指定维度(即在方括号中指定数字来限制数组大小)。那么,如何限定数组的大小呢?有以下两种方式: ① 使用初始化列表 int[] array = {1, 2, 3, 4, 5, }; 注:初始化列表的最后一个逗号是可选的(这一特性使维护长列表变得更容易)。
② 使用new int[] int[] array; array = new int[5]; //分配一个含有5个int型元素大小的数组,所有元素自动初始化为0 |
● 不同于C/C++,在JAVA中,允许将一个数组整体赋值给另一个数组。
不同于C/C++,在JAVA中,允许将一个数组整体赋值给另一个数组。如下:
|
2 3 4 5 6 |
● Java 为什么数组名.length就能获取数组的长度
a.length()是求字符串长度的方法,所以你a的类型为String a.length 是求数组的长度.length是数组的成员变量 |
java数组是java原生支持的,本质是由底层c支持的,你可以从jdk安装路径下include下的jni.h中得到一点点启发, 有一个函数GetArrayLength用来支持获取数组长度. 如果你想看源码,可以下载一个openJDK. |
●我们可以把两个不同名的类放在一个.java文件里面
※ 编程的好习惯: 一个class(类)写在一个java文件中, 尽量不要把多个类写到一个.java文件中. |
不过, 其实我们也可以把两个不同名的类放在一个.java文件里面, 如:
结果:
|
也可在同一个包里面建两个.java文件, 如:
结果:
|
●在Java中,null值表示
在Java中,null值表示引用不指向任何对象。运行过程中系统发现使用了这样一个引用时, 可以立即停止进一步的访问,不会给系统带来任何危险。 注意在Java中null应小写,和其他语言中的用法不同。
String s=null;只是定义了一个句柄,也就是说你有了个引用,但是这个引用未指向任何内存空间 句柄是一个(通常为32位的)整数,它代表一个对象。 |
● 如何理解"this()必须放在第一行,是因为在构造器之前是没有对象"?
this()和super()的作用就是实例化对象, 所以必须把this()或者super()放在第一行,实例化对象之后,才能执行构造器后面的内容。 |
● 有关构造函数的重载
C++构造函数的重载在一个类中可以定义多个构造函数,以便提供不同的初始化的方法,供用户选用。 例如, 我们可以用不同的模子制造出不同的工艺品. 大自然用相同化学材料制造出男人和女人. |
●friendly
用friendly来表示,注意friendly不是Java中的关键字,同一个包内其它类可以访问,但包外就不可以。 对于同一个文件夹下的、没有用package的classes,Java会自动将这些classes初见为隶属于该目录的default package,可以相互调用class中的friendly成员。 如以下两个class分别在同一个文件夹的两个文件中,虽然没有引入package,但隶属于相同的default package。
对于类来说:在同一包中的类可以相互引用, 不用import相关类,但类只可以声明为public或者friendly。 |
● this的两个用法
this.xx 表示调用当前类的对象的成员变量xx this(xx) 表示在该构造函数内调用 形参为xx的另一个同名的构造函数(不常用). 例如:
|
●两种toString()方法
|
ABC [I@c17164 [I@c17164 [65, 66, 67] A 65 |
Object 类的 toString()方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符"@"和此对象哈希码的无符号十六进制表示组成。 Arrays类的toString()方法是返回指定数组内容的字符串表示形式。 |
● java 中的传递
对于java中的值传递和引用传递一直颇受争论,《Core Java》的作者,以及JAVA的创造者James Gosling都认为当一个对象或引用类型变量被当作参数传递时,也是值传递,这个值就是对象的引用,因此JAVA中只有值传递,没有引用传递。还有一种说法是引用可以看作是对象的别名,当对象被当作参数传递给方法时,传递的是对象的引用,因此是引用传递。而《Thinking in Java》一书的作者Bruce Eckel则站在了中立的立场上。
大都数人其实都倾向于第一种说法,java中没有引用传递。 |
● Java中的引用
|
C++中的引用是另一个变量或对象的别名,对引用的操作就是对某变量或对象实体的操作。 |
Java中的引用(准确的说是"引用变量",它保存了它所指向的对象的的地址, 引用都在栈里,而对象在堆中. |
● equals()方法
JAVA当中所有的类都是继承于Object这个超类的,在Object类中定义了一个equals()的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被复写了,如String、Integer、Date。在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。 所以说,对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是内存中的存放位置的地址值,跟双等号(==)的结果相同;如果被复写,按照复写的要求来。
面试题:请解释字符串比较之中"=="和equals()的区别? ==:比较的是两个字符串内存地址的数值是否相等,属于数值比较; equals():比较的是两个字符串的内容,属于内容比较。
准确地说, 在默认情况下: 我们比较的无非是: 1、基本数据类型比较 2、引用对象比较 1、基本数据类型变量的比较 ==和Equals都比较两个变量的值是否相等。相等为true 否则为false;
2、引用类型变量的比较 ==和equals都是比较栈中的两个引用变量是否指向同一对象, 即堆中的内容是否相同。相等为true 否则为false. 不过, 我们可以重写equals()方法.(Java不可以进行运算符的重载) |
●Java 引用变量有两种类型:一个编译期类型,一个运行时类型。
Java 引用变量有两种类型:一个编译期类型,一个运行时类型。编译时类型由该声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定,如果编译时类型和运行时类型不一致,就会出现"多态"现象 |
●继承:
(1)子类的构造方法一定会调用父类的构造方法。 (2)任何子类构造方法第一行肯定是this();或者super();两个择一。 this();调用本类的其它构造方法。(不是一般的成员方法; 传递相应参数调用相应的方法) super();调用父类的构造方法。 (3)如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法,则系统默认调用父类无参数的构造方法.
---子类创建实例对象的时候是否可以调用父类(抽象类)的构造方法?这里是必须调用的。
(4)如果子类构造方法中既未显式调用父类构造方法,而父类中又没有无参的构造方法,则编译出错 (5)构造方法不能继承:子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法 (6)父类构造方法:子类的构造方法必须调用父类的构造方法! |
也就是说当一个类你没有给它构造函数,则编译器会自动补上一个无参的。 每个类至少要有一个构造函数,如果你自己构建了一个带有参数的构造函数而没有再显示的写出无参的构造函数是可以的,不过当你尝试通过一个无参的构造函数来构建(new)时,此时编译器才会报错,因为找不到。 |
● 如果父类的构造函数有自定义的有参函数(即默认的无参构造函数不再存在)
1. 如果一个类没有任何构造函数,系统会默认有一个无参构造函数; 创建有参构造函数后,这个类就不再有默认无参构造函数。 2. 构造函数不能继承,只是调用而已。 如果父类没有无参构造函数, 创建子类时, 不能编译,除非 ①在构造函数代码体中第一行显示调用父类有参构造函数; ②在父类中添加一个无参构造函数. |
解决办法: ①显式调用父类有参构造器: ②写一个父类无参数构造器: 可以通过super()调用父类的构造函数,如果子类没有显式的调用父类的构造函数,则编译器会在子类的构造函数第一行加上super()调用,当然这里只能调用其父类的无参数的构造函数。当然你也可以自己写出具有参数的super()函数来调用父类的带参构造函数。 ★可以通过this()从某个构造函数中调用同一个类的另外一个构造函数。this()只能存在于构造函数中,且同super()一样,只能位于第一行语句。因此super()与this()不可兼得。 |
●对象实例化过程:
(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的) 1.为父类的静态属性分配空间并赋于初值 1.执行父类静态初始化块; (2)加载子类 2.为子类的静态属性分配空间并赋于初值 2.执行子类的静态的内容; (3)加载父类构造器 3.初始化父类的非静态属性并赋于初值 3.执行父类的非静态代码块; 4.执行父类的构造方法; (4)加载子类构造器 5.初始化子类的非静态属性并赋于初值 5.执行子类的非静态代码块; 6.执行子类的构造方法. 总之一句话,静态代码块内容先执行(父先后子),接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。 |
●对象实例化过程的示例代码:
|
静态变量 静态初始化块 变量 初始化块 构造器 |
类的生命周期 |
● 一个Eclipse小技巧
如果我们复制了一段类的代码, 右击一个包名, 粘贴, Eclipse会自动为我们创建一个.class文件, 这个文件里的package 包名; 也自动为我们写好了. 以上面的TestInstanceInit类代码为例: |
● 基类成员在派生类中的访问属性: 对比C++和Java
|