Java基础程序设计

认识Java(仅记录此前未知的知识点)

什么是Java

  • Java前身是Oak
  • Sun公司被Oracle收购
  • JDK是整个java开发的核心,它包含了JAVA的运行环境和JAVA工具
  • JDK,Jre,IDE概念辨析

Java运行机制和JVM

  • 所有*.class文件都是在JVM上运行,由JVM去适应各个操作系统,由此实现可移植性。
  • javac用来将*.java编译成 *.class

语言特点

  • 解释型,效率相比C++较低,但通过在不同平台运行解释器实现了“一次编写,到处运行”
  • 适合分布式计算,联网能力强大而易于使用
  • 稳定,防患于未然,在伪编译时就能发现许多在其他语言中必须通过运行才能发现的错误
  • 多线程处理能力强
  • 是一种动态语言,可以将新代码加入正在运行的程序中

第一个Java程序的实现

  • 使用public class定义要求文件名称与类名称一致,且只能有一个 public class定义
  • 使用class定义的类文件名称可以与类名称不一致,但每一个使用class声明的类都会生成一个*.class文件
  • 应坚持类名称首字母大写
  • Java大小写敏感
  • System.out.println()输出后追加一个换行
  • SET CLASSPATH=e:\balabala可用来指定Java类的执行路径,但是不推荐使用
  • PATH指的是可执行命令的程序路径, CLASSPATH是所有*.class文件的执行路径

简单的Java程序

  • 文档注释(/**)( */)。内容会被解释成程序的正式文档,用以说明该程序的层次结构及方法 (不理解

  • 标识符不能以数字开头,不能是保留关键字,可由任意顺序的大小写字母数字下划线美元符号组成

Java基础程序设计

1
2
3
int max = Integer.MAX_VALUE; //int最大值,同格式可求long最小值等
System.out.println((max + 2L));
System.out.println(((long)max + 2)); //两种强制类型转换的方法
  • Unicode是跨平台的字符码系统,被Java使用
1
2
3
4
5
char ch1 = 'a'; //直接赋值字符需要加''
char ch2 = 97; //或者整形转字符
char ch3 = '\'';
char ch3 = '\\'; //使用转义符赋值特殊符号
String str = "haha"; //String赋值使用""
  • Java数据类型默认值基本都是0
1
2
3
4
5
if (10 != 10 & 10 / 0 == 0) //与 报错
if (10 != 10 && 10 / 0 == 0) //短路与 不报错
if (10 == 10 && 10 / 0 == 0) //使用短路与 仍然报错,因为第一个条件不满足
//短路与,短路或: 第一个条件满足后,后面条件不再判断
//短路不能用于位运算上
  • 括号也属于运算符,作用是提高表达式优先级

  • 异或:异为1

  • 正数原码补码反码都一样,负数的反码是除符号位为1外,其他位全取反,补码是反码加一

  • 负数在计算机里以补码储存

  • a /= b-- 相当于计算a = a / b后,再计算b–. a /= ++b相当于b++后计算a = a / b;

  • 一个字节8位,int32位,long64位,char2位,byte8位,short16位,float32位,bouble64位。

选择与循环语句

  • switch语句加break,case后面有‘:’,关键字default

数组与方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int score[] = null; //数组的声明
score = new int[3];
// int score = new int[3]; //简写形式
int a[] = {11, 22, 33, 44}; // a[0] 为 11 ,以此类推。
int b[][] = new int[3][3]; //二维数组的声明
int c[][] = {{67, 61}, {23, 54, 53}, {99, 88, 77, 66, 32}};
/* 静态初始化一个二位数组
67, 61
23, 54, 53
99, 88, 77, 66, 32
*/

public class Demo { // 向方法中传递数组
public static void main(String[] args) {
int temp[] = {1, 3, 5};
fun(temp);
for (int i = 1; i <= temp.length(); i++) {
System.out.print(temp[i] + " ");
}
}
public static void fun(int x[]) { //x[]和temp[]指向同一个堆内存
x[0] = 6;
}
} //output: 6 3 5

for(int x : arg){
System.out.print(x + " ");
} //foreach输出,但尽量使用原始输出方式。
  • 栈内存保存地址,堆内存保存数据
  • 方法和函数是同样的概念,面向对象常常称之为方法
  • 方法的重载:方法名称相同,但参数的类型和参数的个数不同,通过传递的不同来完成不同方法的调用, 要独立编写
  • 重载的方法也可以有不同的返回值,但从开发的角度来所,应该统一返回值
  • public static void fun(int... arg) 可变参数,即传入的参数 数目随意

8.30

Java面向对象程序设计

面向对象编程基础篇

概念

面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。

特点

个人浅显理解,可能不准确。

  • 封装性:把属性和方法合并,把一些用户不需要知道的内容隐藏,使其不能任意更改。比如把name和getname方法写在Person类内,用户可以使用getname,但是不能更改功能。再比如用户只要使用getname,而不能知道实现方法。
  • 继承性:比如类库有类Person,想做一个类OldPerson,便可以继承Person所有内容,还可添加其他内容。
  • 多态性:允许重名现象,比如可变参数。

对象的创建及使用

  • 同数组,对象名称(即地址)存储与栈内,而属性存储与堆内。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ClassTest {

public static void main(String[] args) {
Person per1 = new Person();
Person per2 = null;
per2 = per1;
per1.name = "Wuhaoda";
per1.age = 17;
per2.name = "HoldenWu";
per2.age = 18;
per1.tell();
per2.tell();
}
}
  • 令对象等于另一个类相同的对象,即令二者所指向的堆内存相同,修改时是对同一块堆内存操作。
  • 垃圾对象可被GC垃圾收集机制释放
  • setter的意义之一:对读入数据进行限制,getter意义:有目的的获取信息,可获取调用次数等。

构造方法

  • 一个类中,即使没有声明构造方法,系统也会自动生成一个构造方法
  • 构造方法也可以重载,重载的方法应该按照规范即参数数量从多到少或从少到多排序。

匿名对象

用处暂不清楚,使用方法:

1
new Person("HoldenWu", 17).tell();

此处不使用栈内存,直接使用堆内存。匿名对象使用一次后即被GC回收。

String类

  • 不能直接用 == 比较st1与st2,这是在比较地址。应该使用equals()比较: st1.equals(st2);
  • 一个字符串就是String的匿名对象。可用"hello".equals(“hello”)比较。 好神奇

假如一个程序要求如下:用户输入一个单词,判定是否为“hello”。但是难免会遇到用户并没有输入的情况。

此时input = null,而运行input.equals(“hello”)就会报错。解决方法是改成"hello".equals(input)。妙啊

深入思考此案例,变量具有可变性,可变性总会带来麻烦的特例。此时不妨换个角度从“不变”的方向入手

  • String类的两种实例化方式,推荐使用直接赋值法。使用直接赋值法,若是后续对象与已存在的对象属性相同,便不会新开辟堆内存,而是直接指向已存在的内存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class StringTest {

public static void main(String args[]) {
String s1 = "hhh";
String s2 = "hhh";
String s3 = "hhh";
s1 = "FUCK";
System.out.println(s2 == s3);
}
} //output ture


public class StringTest {

public static void main(String args[]) {
String s1 = new String("hhh");
String s2 = new String("hhh");
String s3 = new String("hhh");
s1 = "FUCK";
System.out.println(s2 == s3);
}
}//output false
  • 字符串内容不可改变,str = “hello”; str = "world"实际上是新开辟了一个堆内存“world”,然后str由前者指向了后者,这样前者就会变成垃圾空间。由此,不要频繁改动String对象

这里有个疑问,个人感觉数组也像一个对象(查阅资料后发现的确如此)。那么类比一下,是不是数组也不可改变呢?百度后了解到,不是。整个数组是一个堆内存,而堆 为什么String的堆内存不能更改?所有堆内存都不能改吗?(好像不是的),总之自己又懵了,这个问题不了了之吧=.=

  • OI经验告诉我,记忆String方法没用,多使用就会熟。
  • 必要时记得转义(如. / 等)

引用传递及基本应用

注意String的不可修改性。

  • 定义:把堆内存空间的使用权交给多个栈内存空间

一对一关系

  • 简单Java类:属性,构造方法,setter和getter方法

  • 一对一关系:一个类中的成员也是一个

this关键字

  • 可使用this调用本类中的属性(容易理解)
  • 使用this调用构造方法。比如一个类有许多构造方法,而要求对象一被实例化,就必须打印一条提示信息。此时可以设置一个无参数的构造方法打印该信息,在其它构造方法首行使用this()。
  • 使用this表示当前类
  • 构造方法要有出口,不能死循环 套娃警告
  • 直接输出一个类,会打印出地址名称

static关键字

  • 使用static声明的属性/方法会被存储于全局数据区/全局代码区,所有对象共享
  • 可以使用类名称.static 由类名称直接调用
  • static声明的方法不能调用非static声明的属性和方法(我的理解是,static声明的方法存放于全局代码区,不经过实例化即可使用,而此时非static声明的属性和方法由于未实例化,没有被分配空间,所以不能调用。)
  • static可应用于对象的自动编名,统计实例化对象数目等。
  • 由于main使用static声明,所以主方法直接调用的方法必须加上tatic

main函数

当输入java Name xxx时, xxx即为参数,保存于args数组之中。

我猜想args数组的作用是取出参数,进行相应功能的执行,

比如git push -m时,执行的是push文件 -m即为参数,被取出后通过判断执行相应功能。

代码块

普通代码块

1
2
3
4
5
6
7
8
9
10
public class Demo {
public static void main(String args[]) {
{
int x = 30;
System.out.println(x);
}
int x = 100;
System.out.println(x);
}
}

output: 30, 100;

普通代码块用来给代码分割

构造块,静态块

静态块:用static申明,JVM加载类时执行,仅执行一次

构造块:类中直接用{}定义,每一次创建对象时执行

执行顺序优先级:静态块>main()>构造块>构造方法

1.静态块其实就是给类初始化的,而构造代码块是给对象初始化的。

2.静态代码块只会运行一次

3.静态块中的变量是局部变量,与普通函数中的局部变量性质没有区别。
一个类中可以有多个静态代码块,执行顺序按照位置决定。

构造方法私有化

对构造方法进行封装可实现单例设计模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Singleton {
private static Singleton instance = new Singleton();
private int num;
private Singleton() { }
public static Singleton getSingleton() {
return instance;
}
public void print() {
System.out.println("Hello World");
}
public void setNum(int num) {
this.num = num;
}
public int getNum() {
return this.num;
}
}


public class SingletonTest {

public static void main(String args[]) {
Singleton s1 = Singleton.getSingleton();
Singleton s2 = Singleton.getSingleton();
Singleton s3 = Singleton.getSingleton();
s1.setNum(1);
s2.setNum(2);
s3.setNum(3);
System.out.println(s1.getNum());
System.out.println(s1.getNum());
System.out.println(s1.getNum());
}
}

outout: 3 3 3

对象数组

使用的时候必须对每一个对象分别实例化,否则都是null(new两次)

1
2
3
4
5
6
Person per[] = new Person[3] //第一次new
for (int i = 0; i <= 2; ++i)
System.out.print(per[i] + " "); //output null null null
per[0] = new Person("wu");
per[1] = new Person("hao");
per[2] = new Person("da"); //第二次new

对象比较

可以先比较地址是否相等 (直接per1 == per2)

然后判断是否为null