HeadFirst Java
本人有C语言基础,通过阅读Java廖雪峰网站,简单速成了java,但对其中一些入门概念有所疏漏,阅读本书以弥补。
第一章 Java入门
第二章 面向对象
第三章 变量
第四章 方法操作实例变量
第五章 程序实战
第六章 Java函数库
第七章 继承与多态
第八章 深入多态
第九章 构造器与垃圾收集器
第十章 数字与静态
前言
七八九章是Java中较新的知识点,这部分也是区别于C比较有趣的地方!建议大家多多回顾。不多废话,我们进入今天的正题。本章内容较多,其实格式化之后的内容可以另开一章讲了~
先从Math方法,最接近全局的方法开始
Java中没有东西是全局的,但我们有 不依靠实例变量的方法,永远执行相同的工作。比如Math类中的数学方法。没有必要为了执行max()而在堆上建立Math的实例对象。
所以实际的情况是:不会有Math类的实例变量(对象)。Math的构造函数标记为私有!而该类中所有方法都是静态的,无需Math实例,只会用到类模板本身。
静态与非静态方法
static 用于标记不需类实例(对象)的通用方法。——即不依靠实例变量(状态),即不需要对象的方法。
前几章我们知道对象 有状态和行为,状态会影响行为,而通用的方法并不需要知道对象的状态,或者该说与对象无关。
通过标记私有的构造函数来限制非抽象类被初始化,因为被标记private的方法只能在同一.class类里的程序所调用。
静态的方法不能调用非静态的变量、方法——因为他不知道这是谁的
public class Duck {
private String name;
public String getName(){
return name;
}
public static void main(String[] args) {
// Animal a = new Animal("aaa");
System.out.println(name);//以下报错,静态方法(定义上是标记不依赖状态(实例变量)的方法)不知道name是哪只鸭子的name,获取不到实例
System.out.println(getName());//getName会调用到name,那么又回到上面的问题。
}
}
Duck d = new Duck();
d.main(new String());
这两行代码虽然合理,但用对象调用静态方法,并不代表main知道是哪个对象,只是编译器解析出对应的类。
静态变量
作用:被同类的所有对象共享的变量,即每个类只有一个静态变量。
P280 Brain Barbell有点小疑惑,只能创建一个实例的类?使用静态变量计数吗
P526解答了这个问题,单例模式
静态变量在类被加载时初始化
- 该类任何对象创建之前
- 该类任何静态方法执行之前
静态变量的提取同样通过类名
某类的静态部分什么时候执行?——JVM直接运行某.class生成的java或在其他类第一次创建该类的实例时JVM会加载
静态的final变量
即常数,名称应该全大写。final表示数值不再变动。
public static final double PI = 3.14
另一种方法,静态初始化程序:
class Math {
public static final double PI;
static {
PI = 3.14159;
}
}
final的其他用法:
非静态变量——值不能被改变
方法——不再被覆盖,但可以重载哦
类——不再被继承
Math的方法
由上文已经知道了什么是静态方法,以及它的工作原理。
random 返回0.0~1.0的double
abs 返回double参数绝对值
round 四舍五入后的整形
min
max
主数据类型包装
当需要以对象方式处理主数据时,就把它包装起来(Java5.0前)
//包装
int num = 100;
Integer Wrap = new Integer(num);
//解开包装
int unWrap = Wrap.intValue();
自动包装(重要的)
无autoboxing
为什么不直接.add(3),∵ArrayList这个集合,util包中的方法参数声明都是传入Object。返回也都是Object
autoboxing:不必区分主数据与对象
为什么不声明ArrayList?
——因为generic类型规则只能指定 类或接口类型
autoboxing不止用于包装解包主数据给collection用。
1.方法的参数
2.返回值
3.boolean表达式
4.数值运算
——非常神奇,可以对Integer对象做递增运算!?
5.赋值(按相对应的包装赋值)
Double x = 5.00;
double a = x;
x = a;
包装的静态方法(很实用)
String转主数据类型:
int x = Integer.parseInt("100");
double d = Double.parseDouble("1.23");
boolean b = new Boolean("true").booleanValue();//boolean没有,不过构造函数传入String创造,再解包装
主数据类型转String:
double d = 42.5;
String str = ""+d;// + 是java中唯一有重载的运算符
String str = Double.toString(d);//静态方法
数字的格式化
Java 5.0 通过java.util.Formatter类提供,将实用方法加入到了 输入输出、String类上。
只需调用静态方法,传入参数即可(格式设定)
%语法
String s = String.format("%,d",1000000);
%.2f
%,.2f
%[argument number][flag][width][.precision]type //type不可缺少
String s = String.format("%,d %.1f",1000000,1.00)//三个参数,格式化串,一值,二值;依序对应%
多个参数是否意味着.format有许多重载版本?——NO,为了应付格式化的API,Java有新功能:可变参数列表(varable argument list)
日期 (不太重要)
Date类,取得当前的日期时间
String.format("%tc",new Date()); //日期与时间
%tr //时间
%tA,%tB,%td //周月日
String.format("%tA,%<tB,%<td",new Date()); //<表示复用上一个参数
其余功能,Calender类(抽象类)
Calender cal = Calender.getInstance();
由前面几章学习,抽象类无法new一个具体实例。但可以用类下的静态方法。
这一句实际是返回其子类的对象,即Calender的多态响应版本,遵守Calender的合约方法
import java.util.Calendar;
public class Test {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2004,1,7,15,40);
long day = c.getTimeInMillis();//转化为ms
day+=1000*60*60;
c.setTimeInMillis(day);
System.out.println(c.get(c.HOUR_OF_DAY));
}
}
静态的Import
静态import类,之后其静态方法、变量、enum,后面不需重复多打
类似Math类,书中这里称之为静态类,但其实好像前文没这概念,只是把构造函数私有化,然后类的方法都是静态通用方法。
//旧的写法
import java.lang.Math;
public class Test {
public static void main(String[] args) {
System.out.println(Math.sqrt(100));
}
}
//静态Import
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
System.out.println(sqrt(100));
}
}
其他:实例变量与静态变量
P308~309 可能质疑静态变量不够面向对象?
System.out, out是System类中的一个静态变量,不必创建其实例,从类调用变量即可
共享的类可以省下很多内存
SwingConstant,该类用来存放常数;
Color类,存放RGB值
总之,静态变量是在对象的类中,可以高效率被共享。有一定的不可替代性。
一些练习
会输出什么呢?
class Test {
static {
System.out.println("Before JVM");
}
public static void main(String[] args) {
System.out.println("Start");
new Test();
}
}
class Test {
static int x;
static {
System.out.println("Before JVM");
System.out.println(x);
}
static {
x= 5;
System.out.println(x);
}
public static void main(String[] args) {
System.out.println("Start");
new Test();
}
}
public class Test1 {
public static void main(String[] args) {
System.out.println("ok");
new Test();
}
}
JVM加载类时,静态初始化程序(关于静态的东西)就会运行。
JVM何时加载类?——JVM直接运行某.class生成的java或在其他类第一次创建该类的实例时JVM会加载