Preface · 序
本文为已归档的历史博客内容,其内容可能随着时间发生已经改变。
This article is archived from my previous blog, so the content maybe have changed now.。
初学 Java 4 Android - Note & Code
2015.09.13 by kingcos源自《[Java 4 Android](http://study.163.com/course/courseMain.htm?courseId=201001)》-- [Mars](http://www.marschen.com/portal.php) 如有错误,希望指出。
前言: 本文档不能保证完全正确,如有错误,希望可以指出,但不再另行通知。本文仅作整理及个人学习使用,版权仍归视频作者 Mars 所有。
笔记:
Info:
- Java SE 1.8
- Mac OS X 10.10
- 本文已于 2015.11.17 日基本完成,由于 J4A 系列视频仅有 54 集,后续不知去向,暂且如此,综合练习的代码未来可能会更新于此
面向对象基础
(一)
笔记:
什么是面向对象?
- 面向对象时一种编程方法
- 面向对象是一种思维方式
- 面向对象不是一种编程语言
如何学习面向对象?
- 掌握一门面向对象语言的语法
- 掌握面向对象的思维方式
- 熟悉面向对象设计原则
- 掌握面向对象的设计模式
面向对象最终目标:消除重复代码
什么是面向对象思维模式?
- 首先确定谁来做,其次确定怎么做
- 首先考虑整体,其次考虑局部
- 首先考虑抽象,其次考虑具体
(二)
笔记:
定义类:
class 类名
{
属性(即成员变量);
方法(即成员函数);
}
类的表示方法:类名+成员变量+成员函数
如果一个方法中有与成员变量同名的局部变量,该方法中对这个变量名的访问是局部变量,而不再是成员变量。
对象是引用数据类型:
- JVM 将其分成两个内存:栈内存+堆内存
- 栈内存存放对象的名字,即引用(其本身并不是对象)
- 对象的本体存放在堆内存(
new
的时候开辟空间)
Dog d = new Dog();
// d 不是对象,而是对象的引用
类是抽象的,对象是具体的
(三)
笔记:
匿名对象(一次性):
new Dog().jump();
new Dog().jump();
// 这两个对象并不一样
(四)
笔记:
重载
- 两个或者多个函数在同一个类当中
- 函数名相同
- 参数列表不同
构造函数:
- 如果类中没有构造函数,编译器会生成默认构造函数(参数和方法体为空);
- 如果类中已有构造函数(无论参数是否为空),那么就没有默认的构造函数。
this 的使用方法
笔记:
this
调用函数:
- 调用本类当中的其它构造函数函数:
this.test(name, age);
- 必须放在构造函数语句的第一个
- 根据参数个数或类型判断调用哪个构造函数
Static 关键字的作用
笔记:
静态变量:
class Person {
static int i;
}
Person p1 = new Person();
Person p2 = new Person();
Person.i = 10; // 均 10
p1.i = 20; // 均 20
p2.i = 30; // 均 30
调用静态变量可以(非必须)直接通过类名调用
只要更改 static
变量,所有对象中成员变量值均改变
static
变量是属于类的,不属于对象
静态函数:
class Person {
static void fun() {
System.out.println("I am static function.");
}
}
Person.fun();
调用静态函数可以(非必须)直接通过类名调用 静态函数内不能使用非静态成员变量
静态代码块:
static {
System.out.println("I am static code block.");
}
静态代码块要在装载(到内存)这个类的时候执行 可以为静态成员变量赋一些初始值(不常用)
继承
继承初步
笔记:
Java 只支持单继承,不允许多继承 继承是为了减少重用代码
eg:
class Person {
String name;
int age;
void eat() {
System.out.println("Have meals.");
}
void introduce() {
System.out.println("Name is" + name + "Age is" + age);
}
}
class Student extends Person {
int grade;
void study() {
System.out.println("Study");
}
}
子类实例化过程
笔记:
只能继承成员函数和成员变量(不继承构造函数)
在子类的构造函数中,必须调用父类构造函数(为什么?)
没有主动调用的话,编译器会自动为你调用(super();
)
如果想调用其它构造函数,可以填对应的参数
为什么子类必须调用父类构造函数?
super();
- 继承时不能继承构造函数
eg:
Person.java
class Person {
String name;
int age;
Person() {
System.out.println("Person Non-Paraments");
}
Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person With-Paraments");
}
void eat() {
System.out.println("Have meals.");
}
}
Student.java
class Student extancds Person {
student() {
System.out.println("Student Non-parament");
}
}
Test.java
class Test {
public static void main(String args []) {
Student stu = new Student();
}
}
函数的复写(Override)
eg:
Person.java
class Person {
String name;
int age;
void introduce() {
System.out.println("My name is" + name + ", I am" + age + "years old.");
}
}
Student.java
class Student extends Person {
String address;
void introduce() {
super.introduce();
System.out.println("My address is" + address + ".");
}
}
Test.java
class Test {
public static void main(String args []) {
Student s = new Student();
s.name = "MaiMieng";
s.age = 20;
s.address = "USA";
s.introduce();
Person p = new Person();
p.name = "Vitas";
p.age = 30;
p.address = "Russia";
P.introduce();
}
}
笔记:
复写(Override)
- 在具有父子关系的两个类中
- 父类和子类各有一个函数,这两个函数的定义(返回值类型,函数名,和参数列表)完全相同
- 用
super.
调用父类相同的成员函数
重载(Overload)和复写(Override)的不同:
- 重载是在同一个类,复写是在两个类中
- 重载函数的参数个数或类型不同,而复写完全相同
对象的转型
向上转型
笔记:
// class Student extends Person:
Student s = new Student();
Person p = s;
Person P = new Student();
- 对象的向上转型:将子类的对象赋值给父类的引用。
Student s = new Student();
Person p = s;
Student stu = (Student)p;
一个引用能够调用那些成员(变量和函数),取决于这个引用的类型 一个引用调用的是哪一个方法,取决于这个引用所指向的对象
eg:
Person.java
class Person {
String name;
int age;
void introduce() {
System.out.println("My name is" + name + ", I am" + age + "years old.");
}
}
Student.java
class Student extends Person {
String address;
void study() {
System.out.println("Studying");
}
void introduce() {
super.introduce();
System.out.println("My address is" + address + ".");
}
}
Test.java
class Test {
public static void main(String args []) {
Student s = new Student();
Person p = s;
p.name = "MaiMieng";
p.age = 20;
// p.address = "USA";
// p.study();
// THESE ARE MISTAKES!
p.introduce();
// DISPLAY:
// My address is NULL.
}
}
向下转型
笔记:
对象的向下转型:将父类的对象赋值给子类的引用 向下转型的前提是向上转型
eg:
相比向上转型,仅改变:Test.java
class Test {
public static void main(String args []) {
Person p = new Student();
Student s = (Student)p;
// 错误的向下转型:
// Person p = new Person();
// Student s = (Student)p;
}
}
面向对象应用
eg:
Printer.java
class Printer {
void open() {
System.out.println("Open");
}
void close() {
System.out.println("Close");
}
void print(String s) {
System.out.println("Print -> " + s);
}
}
HPPrinter.java
class HPPrinter extends Printer {
}
CanonPrinter.java
class CanonPrinter extends Printer {
void close() {
this.clean();
super.close();
}
void clean() {
System.out.println("Clean");
}
}
Test.java
class Test {
public static void main(String args []) {
int flag = 0;
if(flag == 0) {
HPPrinter hp = new HPPrinter();
hp.open();
hp.print("hp");
hp.close();
} else if (flag == 1) {
CanonPrinter canon = new CanonPrinter();
canon.open();
canon.print("Canon");
canon.clean();
canon.close();
}
}
抽象类和抽象函数
笔记:
abstract void fun();
抽象函数:只有函数的定义,没有函数体的函数
抽象(基)类:使用 abstract
定义的类
- 抽象类不能生成对象(无法实例化),但可以有构造函数(详见下)
- 如果一个类中有抽象函数,则该类必须被声明为抽象类
- 如果一个类没有抽象函数,则该类也可被声明为抽象类
eg:
Person.java
abstract class Person {
String name;
int age;
Person() {
System.out.println("Person's construction.");
}
void introduce() {
System.out.println("My name is" + name + ", I am" + age + "years old.");
}
abstract void eat();
}
Chinese.java
class Chinese extend Person {
Chinese() {
// super();
System.out.println("Chinese's construction.");
}
void eat() {
System.out.println("Chinese Food.");
}
}
Test.java
class Test {
public static void main(String args []) {
Person p = new Chinese();
p.eat();
}
包和访问权限
(一)
笔记:
编译参数:
// -d: 根据包名生成文件夹
javac -d . Test.java
java test.Test
软件包为 Java 类提供了命名空间
打包需要使用 package
指令(package test;
)
一个类的全名应该是:"包名" + "." + "类名"
包名的命名规范:
- 要求包名的所有字母都要小写
- 包名一般情况下,是你的域名倒过来写:
package com.maimieng
(将会先生成com
文件夹) - 建议
package com.maimieng.+...
(二)
笔记:
访问权限:
public
: 公共权限private
: 私有权限(default)
: 包级别访问权限protected
: 受保护权限
public
:
如果一个类是 public
,那么这个类名必须和 .java
文件名相同
public
可以修饰类,成员变量和成员函数
没有任何限制,同一个包或者不同包中的类都可以自由访问
private
:
一般只修饰成员(变量和函数)
一旦成员被 private
修饰,那么其只能在本类中使用
(default)
:
- 在同一个包当中,可以互相访问。
import
:
导入其它包的类(即可省略包的全名:com.maimieng.Person = new com.maimieng.Person();
):
import com.maimieng.Person;
import com.maimieng.*;
// 导入此目录下全部类
(三)
笔记:
如果子类和父类不在同一个包当中,子类可以继承到父类当中的 (default)
权限的成员变量和成员函数,但是由于权限不够,无法使用
protected
该权限只能修饰成员变量和成员函数
父类的 protected
可以为跨包的子类所用
public > protected > (default) > private
接口的基本语法
笔记:
class USBphone implements USB {}
定义了接口就是定义了调用对象的标准
接口中所有方法为 public
权限
实现接口使用 implements
关键字
一个类可以实现多个接口
一个接口可以继承多个接口
eg:
一个类实现两个接口
USBphone.java
class USBphone implements USB, Wifi {
@Override
public void read() {
System.out.println("READ");
}
@Override
public void write() {
System.out.println("WRITE");
}
@Override
public void open() {
System.out.println("OPEN");
}
@Override
public void close() {
System.out.println("CLOSE");
}
}
USB.java
interface USB {
public void read();
public void write();
}
Wifi.java
interface Wifi {
public void open();
public void close();
}
Test.java
public class Test {
public static void main(String args []) {
USBphone up = new USBphone();
USB usb = up;
usb.read();
usb.write();
Wifi wifi = up;
wifi.open();
wifi.close();
}
}
一个接口继承两个个接口
A.java
interface A {
public void funA();
}
B.java
interface B {
public void funB();
}
C.java
interface C extends A, B {
public void funC();
}
接口的应用
Printer.java
interface Printer {
public void open();
public void close();
public void print(String s);
}
HPprinter.java
class HPprinter implements Printer {
@Override
public void open() {
System.out.println("HP open");
}
@Override
public void close() {
System.out.println("HP close");
}
@Override
public void print(String s) {
System.out.println("HP -> " + s);
}
}
CANONprinter.java
class CANONprinter implements Printer {
private void clean() {
System.out.println("CANON clean");
}
@Override
public void open() {
System.out.println("CANON open");
}
@Override
public void close() {
this.clean();
System.out.println("CANON close");
}
@Override
public void print(String s) {
System.out.println("CANON -> " + s);
}
}
PrinterFactory.java
class PrinterFactory {
public static Printer getPrinter(int flag) {
Printer p = null;
if (flag == 0) {
p = new HPprinter();
} else if (flag == 1) {
p = new CANONprinter();
}
return p;
}
}
Test.java
public class Test {
// 根据用户的选择,生成相应的打印机对象
// 并且向上转型为 Printer 类型
// Printer getPrinter(int flag);
public static void main(String args []) {
int flag = 1;
Printer p = PrinterFactory.getPrinter(flag);
p.open();
p.print("test");
p.close();
}
}
Java 当中的异常
(一)
笔记:
异常的分类:
异常(Exception):中断了正常指令流的事件
- 异常不同于语法错误,运行时产生,不同于编译时
- 异常是一个对象,由 JDK 中的类生成(如上图)
- 分为两类:运行时异常(Uncheck, RuntimeException 子类),编译时异常(Check)
- 对异常的处理关系到系统的健壮性
- 使用
try catch finally
处理可能出现异常的代码
Error: 虚拟机在运行的时候产生的错误,然后直接关闭 程序员对 Error 无能为力,只能处理 Exception
eg:
public class Test {
public static void main(String args []) {
// Uncheck exception:
// int i = 1 / 0;
// Check exception:
Thread.sleep(1000);
}
}
public class Test {
public static void main(String args []) {
System.out.println(1);
try {
System.out.println(2);
int i = 1 / 0;
System.out.println(3);
}
catch (Exception e) {
System.out.println(4);
e.printStackTrace();
System.out.println(5);
}
System.out.println(6);
}
}
public class Test {
public static void main(String args []) {
try {
Thread.sleep(1000);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
// 放一些诸如文件关闭等关闭资源的操作
System.out.println("Finally");
}
}
}
(二)
eg:
User.java
class User {
private int age;
// 声明有可能产生异常(即其没有责任处理异常,谁调用谁处理):
public void setAge(int age) throws Exception {
if (age < 0) {
Exception r = new Exception("TEST");
// 抛出异常:
throw r;
}
this.age = age;
}
}
Test.java
class Test {
public static void main(String args []) {
User u = new User();
try {
u.setAge(-20);
}
catch (Exception e) {
System.out.println("Test");
}
}
}
Java 当中的 IO
(一)
笔记:
I/O 操作的目标:从数据源当中读取数据,以及将数据写入到数据目的地当中
I/O 流向:
IO 分类: 一:
- 输入流
- 输出流
二:
- 字节流
- 字符流
三:
- 节点流
- 处理流
I/O 当中的核心类:
InputStream
& OutputStream
(抽象类)是所有字节流的父类
核心类的核心方法:
// InputStream
int read(byte[] b, int off, int len)
// OutputStream
void write(byte[] b, int off, int len)
eg:
// 导入类
import java.io.*;
class Test {
public static void main(String args []) {
// 声明输入流引用
FileInputStream f = null;
// 声明输出流引用
FileOutputStream o = null;
try {
// 生成代表输入流的对象
f = new FileInputStream("/Users/MaiMieng/Documents/workspace/1.txt");
// 生成代表输出流的对象
o = new FileOutputStream("/Users/MaiMieng/Documents/workspace/2.txt");
// 生成一个字节数组
byte[] buffer = new byte[100];
// 调用输入流对象的 read 方法,读取数据
int t = f.read(buffer, 1, buffer.length - 1);
o.write(buffer, 0, t);
// String s = new String(buffer);
// System.out.println(s);
// 调用一个 String 对象的 trim 方法,将会去除掉这个字符串的首尾空格和空字符
// s.trim();
// for (int i = 0; i < buffer.length; i++) {
// System.out.println(buffer[i]);
//}
}
catch (Exception e) {
System.out.println(e);
}
}
}
(二)
笔记:
字符流:读写文件时,以字符为基础
字节输入流:Reader
<- FileReader
字节输出流:Writer
<- FileWriter
int read(char [] c, int off, int len)
void write(char [] c, int off, int len)
eg:
字节流:
import java.io.*;
class Test {
public static void main(String args []) {
FileInputStream i = null;
FileOutputStream o = null;
try {
i = new FileInputStream("/Users/MaiMieng/Documents/workspace/1.txt");
o = new FileOutputStream("/Users/MaiMieng/Documents/workspace/2.txt");
byte[] buffer = new byte[1024];
while (true) {
int t = i.read(buffer, 1, buffer.length - 1);
if (t == -1) {
break;
}
o.write(buffer, 0, t);
}
}
catch (Exception e) {
System.out.println(e);
}
finally {
try {
i.close();
o.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
字符流:
import java.io.*;
class Test {
public static void main(String args []) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("/Users/MaiMieng/Documents/workspace/1.txt");
fw = new FileWriter("/Users/MaiMieng/Documents/workspace/2.txt");
char[] buffer = new char[100];
int t = fr.read(buffer, 0, buffer.length);
// for (int i = 0; i < buffer.length; i++) {
// System.out.println(buffer[i]);
// }
fw.write(buffer, 0, t);
}
catch (Exception e) {
System.out.println(e);
}
finally {
try {
fr.close();
fw.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
(三)
笔记:
字符输入处理流 BufferedReader
介绍:
- 读取一行数据
BufferedReader in = new BufferedRead(new FileReader("foo.in"));
eg:
Test.java
import java.io.*;
class Test {
public static void main(String args []) {
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("/Users/MaiMieng/Documents/workspace/1.txt");
br = new BufferedReader(fr);
String l = null;
while (true) {
l = br.readLine();
if (l == null) {
break;
}
System.out.println(l);
}
}
catch (Exception e) {
System.out.println(e);
}
finally {
try {
br.close();
fr.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
装饰者模式:装饰者给被装饰者提供功能
Aworker.java
// Aworker 是装饰者,Carpenter & Plumber 是被装饰者
class Aworker implements Worker {
private Worker worker;
public Aworker(Worker worker) {
this.worker = worker;
}
public void doSomeWork() {
// 先执行都需要执行的函数,再转型
System.out.println("Hello");
worker.doSomeWork();
}
}
内部类和匿名内部类
笔记:
内部类:
class A {
// B 是 A 的内部类,编译后生成 A$B.class
class B {
...
}
}
内部类可以使用外部类的成员变量和成员函数,但并不代表内部类是外部类的继承
匿名内部类:
eg:
内部类:
Test.java
class Test {
public static void main(String args []) {
A a = new A();
// 生成内部类对象,必须先有外部类对象
A.B b = a.new B();
// 类似:A.B b = new A().new B();
a.i = 1;
b.j = 2;
System.out.println(b.funB());
}
}
A.java
class A {
int i;
class B {
int j;
int funB() {
int r = i + j;
// 类似:int r = A.this.i + this.j;
return r;
}
}
}
匿名内部类:
Test.java
class Test {
public static void main(String args []) {
B b = new B();
b.fun(new A() {
// 用来实现 A 的接口:
public void doSome() {
System.out.println("匿名内部类");
}
});
}
}
A.java
interface A {
public void doSome();
}
B.java
class B {
public void fun(A a) {
System.out.println("B's fun()");
a.doSome();
}
}
Java 当中的线程
(一)
笔记:
多进程:在操作系统中能(同时)运行多个任务(程序) 多线程:在同一应用程序中有多个顺序流(同时)执行
线程的执行过程:
实现线程的方法 1:
- 定义一个线程类,它继承类
Thread
并重写其中的方法run()
,方法run()
称为线程体(由于 Java 只支持单继承,用这种方法定义的类不能再继承其它类)
线程运行没有规律
eg:
Test.java
class Test {
public static void main(String args []) {
// 生成线程类的对象
FirstThread ft = new FirstThread();
// 启动线程,不能这样写:ft.run();(这个先执行 ft 线程)
ft.start();
for (int i = 0; i < 100; i++) {
System.out.println("M: " + i);
}
}
}
FirstThread.java
class FirstThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("FT: " + i);
}
}
}
(二)
笔记:
实现线程的方法 2:
提供一个实现接口 Runnable
的类作为线程的目标对象,在初始化一个 Thread
类或者 Thread
子类的线程对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体
线程的简单控制方法:
- 中断线程
Thread.sleep(x);
(要使用 try catch,休眠时间= x 毫秒+抢到 CPU 的时间)
Thread.yield();
(让出 CPU,同时再次去抢,并不一定是另一个线程运行)
- 设置线程优先级:
getPriority();
setPriority();
eg:
实现线程:
RunnableImpl.java
class RunnableImpl implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("RI: " + i);
}
}
}
Test.java
class Test {
public static void main(String args []) {
// 生成一个 Runnable 接口实现类的对象
RunnableImpl ri = new RunnableImpl();
// 生成一个 Thread 对象,并将 Runnable 接口实现类的对象作为参数,传递给该 Thread 对象
Thread t = new Thread(ri);
// 通知 Thread 对象,执行 start 方法
t.start();
for (int i = 0; i < 100; i++) {
System.out.println("M: " + i);
}
}
}
优先级等
Test.java
class Test {
public static void main(String args []) {
// 生成一个 Runnable 接口实现类的对象
RunnableImpl ri = new RunnableImpl();
// 生成一个 Thread 对象,并将 Runnable 接口实现类的对象作为参数,传递给该 Thread 对象
Thread t = new Thread(ri);
// 线程优先级范围:1-10,可通过 Thread 静态常量来设置线程优先级
t.setPriority(Thread.MIN_PRIORITY);
System.out.println(t.getPriority());
// 通知 Thread 对象,执行 start 方法
t.start();
}
}
(三)
eg:
Test.java
class Test {
public static void main(String args []) {
MyThread myThread = new MyThread();
// 生成两个 Thread 对象,但是它们共用同一个线程体
Thread t1 = new Thread(myThread);
Thread t2 = new Thread(myThread);
// Thread 每一个线程都有名字,可通过 setName() 设置,getName() 获取
t1.setName("a");
t2.setName("b");
// 分别启动两个线程
t1.start();
t2.start();
}
}
MyThread.java
class MyThread implements Runnable {
int i = 100;
public void run() {
// 谁获得谁才能运行:
synchronized (this) {
while (true) {
// Thread.currentThread() 获取哪个线程在运行
System.out.println(Thread.currentThread().getName() + i);
i--;
Thread.yield();
if (i < 0) {
break;
}
}
}
}
}
深入同步语法
笔记:
同步代码块:
synchronized()
锁住的是对象(this
即service
)而不代码- 一旦某个线程获得了一个对象的同步锁,那么这个对象上任何被同步的代码统统不能执行
- 同步锁不影响非同步代码
同步方法锁住的是 this
(this
即调用此方法的对象),与同步代码块类似,但同步代码块更灵活(括号内可以放其它对象)
eg:
同步代码块:
Main.java
public class Main {
public static void main(String[] args) {
Service s = new Service();
Thread t1 = new Thread(new MyThread1(s));
Thread t2 = new Thread(new MyThread2(s));
t1.start();
t2.start();
}
}
MyThread1.java
class MyThread1 implements Runnable {
private Service s;
public MyThread1(Service s) {
this.s = s;
}
public void run() {
s.fun1();
}
}
MyThread2.java
class MyThread2 implements Runnable {
private Service s;
public MyThread2(Service s) {
this.s = s;
}
public void run() {
s.fun2();
}
}
Service.java
class Service {
public void fun1() {
synchronized(this) {
try {
Thread.sleep(3 * 1000);
}
catch(Exception e) {
System.out.println(e);
}
System.out.println("fun1");
}
}
public void fun2() {
synchronized(this) {
System.out.println("fun2");
}
}
}
// DISPLAY:
// fun1
// fun2
不会对无同步锁代码屏蔽:
Service.java
class Service {
public void fun1() {
synchronized(this) {
try {
Thread.sleep(3 * 1000);
}
catch(Exception e) {
System.out.println(e);
}
System.out.println("fun1");
}
}
public void fun2() {
// synchronized(this) {
System.out.println("fun2");
// }
}
}
// DISPLAY:
// fun2
// fun1
同步方法:
Service.java
class Service {
public synchronized void fun1() {
try {
Thread.sleep(3 * 1000);
}
catch(Exception e) {
System.out.println(e);
}
System.out.println("fun1");
}
public synchronized void fun2() {
System.out.println("fun2");
}
}
// DISPLAY:
// fun1
// fun2
Java 当中的数组
笔记:
数组长度:.length
动态声明的数组默认值均为 0
或 false
eg:
一维数组:
Main.java
class Main {
public static void main(String[] args) {
// 数组的静态声明法:
int arr [] = {5, 2, 7, 9};
// 数组的动态声明法:
int a [] = new int[10];
arr[3] = 10;
System.out.println(arr[3]);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
// DISPLAY:
// 10
// 5
// 4
// 7
// 10
二维数组:
class Main {
public static void main(String[] args) {
// 二位数组的定义方法:
int arr [][] = {{1, 2, 3}, {4, 5, 6}, {7, 8}};
int a [][] = new int[3][5];
arr[1][1] = 10;
System.out.println(arr[1][1]);
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
}
// DISPLAY:
// 10
// 1
// 2
// 3
// 4
// 10
// 6
// 7
// 8
类集框架
(一)
笔记:
类集框架是一组类和接口
位于 jav.util
包中
主要用户存储和管理对象
主要分为三大类:集合,列表,映射
集合(Set): 集合中的对象不按特定的方式排序,并且没有重复对象
列表(List): 集合中对象按照索引位置排序,可以有重复对象
映射(Map): 集合中的每一个元素包涵一个键对像和一个值对象,键不可以重复,值可以重复
类集框架主体结构
eg:
Main.java
import java.util.List;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.remove(1);
for (int i = 0; i < arrayList.size(); i++) {
String s = arrayList.get(i);
System.out.println(s);
}
}
}
// DISPLAY:
// a
// c
(二)
笔记:
Collection 接口:
继承关系: Iterator <- Collection <- Set <- HashSet Iterator <- Collection <- List <- ArrayList
eg:
Main.java
1:
import java.util.Set;
import java.util.HashSet;
class Main {
public static void main(String[] args) {
// HashSet<String> hashSet = new HashSet<String>();
// Set<String> set = hashSet;
Set<String> set = new HashSet<String>();
boolean b1 = set.isEmpty();
System.out.println(b1);
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("c");
boolean b2 = set.isEmpty();
System.out.println(b2);
System.out.println(set.size());
set.remove("a");
System.out.println(set.size());
set.clear();
System.out.println(set.size());
}
}
// DISPLAY:
// true
// false
// 4
// 3
// 0
2:
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
class Main {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("c");
// 调用 Set 对象的 Iterator 方法,
// 会生成一个迭代器对象,
// 该对象用于遍历整个 Set
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
(三)
笔记:
学会使用 api 文档(推荐一个 iOS & Mac app:dash)
eg:
Main.java
import java.util.Map;
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<String, String>();
Map<String, String> map = hashMap;
map.put("1", "a");
map.put("2", "b");
map.put("3", "c");
map.put("4", "d");
map.put("3", "e");
System.out.println(map.size());
System.out.println(map.get("3"));
}
}
// DISPLAY:
// 4
// e
equals
函数的作用
笔记:
使用 ==
比较引用数据类型:
判断双等号两端的引用是否指向堆内存中的同一个地址/对象
对象的内容相等通常需要符合:
- 对象的类型相同(可以用
instanceof
操作符进行比较) - 两个对象的成员变量的值完全相同
eg:
Main.java
class Main {
public static void main(String[] args) {
User u1 = new User();
User u2 = new User();
User u3 = new User();
u1.name = "Mike";
u1.age = 12;
u2.name = "Michael";
u2.age = 12;
u3.name = "Mike";
u3.age = 12;
System.out.println(u1.equals(u2));
System.out.println(u1.equals(u3));
}
}
// DISPLAY:
// false
// true
User.java
class User {
String name;
int age;
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
boolean b = obj instanceof User;
if (b) {
User u = (User)obj;
if (this.age == u.age && this.name.equals(u.name)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
hashCode()
与 toString()
笔记:
均为 Object
类函数
eg:
Main.java
import java.util.*;
class Main {
public static void main(String[] args) {
User u = new User("Mike", 12);
HashMap<User, String> map = new HashMap<User, String>();
map.put(u, "abc");
String s = map.get(new User("Mike", 12));
System.out.println(s);
System.out.println(u);
}
}
// DISPLAY:
// abc
// age: 12, name: Mike
User.java
class User {
String name;
int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
boolean b = obj instanceof User;
if (b) {
User u = (User)obj;
if (this.age == u.age && this.name.equals(u.name)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public int hashCode() {
int result = 17;
result = 31 * result + age;
result = 31 * result + name.hashCode();
return result;
}
public String toString() {
String result = "";
result = result + "age: " + age + ", " + "name: " + name;
return result;
}
}
开发工具之 Eclipse
(一)&(二) &(三)
略
(四)
笔记:
代码重构: 重构可以改善软件的设计 重构可以让软件更加容易理解 重构可以协助寻找 bug 重构可以提升开发速度
综合练习
暂无