20145226 《Java程序设计》第3周学习总结
教材学习内容总结
学习目标
- 区分基本类型与类类型
- 理解对象的生成与引用的关系
- 掌握String类和数组
- 理解封装的概念
- 掌握构造方法的定义
- 理解重载的概念
- 掌握static的应用
教材第四章内容总结
基本类型和类类型
- 基本类型:第三章中讲述的那几种,short、long、int、byte、double、char、boolean等这些。
- 类类型:指class类型,把一些基本的类型和方法整合到一起,体现出了类的封装特性,便于实现模块化。
类与对象
- 对象(Object):存在的具体实体,具有明确的状态和行为
- 类(Class):具有相同属性和行为的一组对象的集合,用于组合各个对象所共有操作和属性的一种机制
- 从类看对象:类定义可以视为一个具有类似特性与共同行为的对象的模板,可用来产生对象
- 从对象看类:类的产生,是从少数实例,推广到大量相似实例的抽象化过程(abstraction)
- 类是对象的设计图,对象是类的实例,生成对象要先定义类
关于类和对象的关系
Clothes c1 = new Clothes();
c1是引用,在栈上
new Clothes()在堆上生成对象
c1 可以近似看成指向对象的指针
类与对象的关系:要产生对象必须先定义类,类是对象的设计图,对象是类的实例,书上的比喻很贴切:
新建一个对象:使用 new 关键词(例如:new Cloth();)(相当于建立一件衣服)
声明参考名称(声明参考变量)(声明参考):也就是给新变量起个名字(例如:Clothes c1)
将名称参考至新建对象:就是把新变量的名字赋给这个新变量(例如:Clothes c1 = new Clothes();)(给新衣服贴上标签)
定义值域成员(定义对象数据成员):每个新建的实例都可拥有这些对象数据(衣服的各种属性)例如:
class Clothes {
//定义Clothes类,相当于衣服的设计图,里面包含color和size
String color;
char size;
}
public class Field {
public static void main(String[] args) {
Clothes sun = new Clothes();
Clothes spring = new Clothes();
//建立Clothes实例(给新的Clothes起名字,分别叫sun、spring)
sun.color = "red";
sun.size = 'S';
spring.color = "green";
spring.size = 'M';
//为个别对象的数据成员指定值(定义衣服sun和spring的color及size)
System.out.printf("sun(%s,%c)%n", sun.color, sun.size);
System.out.printf("spring(%s,%c)%n", spring.color, spring.size);
//显示个别对象的数据或成员值(显示sun及spring的color和size)
}
}
运行结果:
定义构造函数
函数的意义就是有些操作不需要重复进行,定义完一个函数后,若想进行函数里定义的操作,直接调用函数即可。下面是定义函数及调用函数的例子:
class Clothes2 {
String color;
char size;
Clothes2(String color,char size){
//定义构造函数
this.color = color;
//前一个color:函数里的第一个变量;后一个color:之前定义的值域成员;这句话是把color参数的值指定给这个对象的color成员
this.size = size;
}
}
public class Field2 {
public static void main(String[] agrs) {
Clothes2 sun = new Clothes2("red",'s');
//使用函数建立对象,定义函数之后传入数据即可
Clothes2 spring = new Clothes2("green",'M');
System.out.printf("sun(%s,%c)%n",sun.color,sun.size);
System.out.printf("spring(%s,%c)%n",spring.color,spring.size);
}
}
运行结果:
标准类java.util.Scanner和java.math.BigDecimal
标准API可以省去撰写程序时重新打造基础的需求,包名为java开头的类表示标准API提供的类。
java.util.Scanner
java.util.Scanner 类是一个简单的文本扫描器可以分析基本类型和字符串使用正则表达式:
- 一个扫描器使用分隔符模式分解它的输入,默认情况下与空白匹配。
- 扫描操作可能阻塞等待输入。
- 扫描器是不是安全的,无需外部同步多线程使用。
java.util.Scanner
取得用户输入接收输入函数的使用:
import java.util.Scanner;
public class Guess
{
public static void main(String[] args)
{
Scanner scanner = new Scanner (System.in);
int number = (int) (Math.random() * 10);
int guess;
do
{
System.out.printf("猜数字(0~9):");
guess = scanner.nextInt();
}
while(guess != number);
System.out.println("猜中了...XD");
}
}
运行结果:
注:
Scanner类大大简化了Java的输入,要熟练掌握其方法,关键是会查API文档。
要摒弃掉C的格式化输入输出方式,用java的输入输出接口。
Scanner对每个基本类型,都会有对应的方法,如nextByte()、nextShort()、 nextInt() 、nextLong()、 nextFloat() 、nextDouble() 、 nextBoolean()等
如果直接取得上一个字符串,以空格或者换行分隔,则使用next()
如果取得用户输入的整行文字,则使用nextLine(),以换行分隔。
java.math.BigDecimal
BigDecimal一共有4个够造方法,除了用BigInteger来够造的那两个,还有另外的两个,它们是:
BigDecimal(double val)
Translates a double into a BigDecimal.
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
java.math.BigDecimal
能够提高浮点数精确度,需要用到java.math.BigDecimal
的时候,跟java.util.Scanner
一样,有import java.math.BigDecimal
写程序时每次输入BigDecimal即可
使用java.math.BigDecimal
的小例子:
package net.nyist;
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.1");
BigDecimal c = new BigDecimal("0.1");
BigDecimal result = new BigDecimal("0.3");
if(a.add(b).add(c).equals(result)){
System.out.println("等于0.3");
}else{
System.out.println("不等于0.3");
}
}
}
运行结果:
注:
- 创建BigDecimal的方法之一是使用字符串,BigDecimal在创建时会剖析传入的字符串,以默认精度进行接下来的运算
- BigDecimal提供有plus() substract() multiply() divide() 等方法,可以进行加、减、乘、除等,这些方法的返回BigDecimal类型
对象指定与相对性
- “”与“equals()”的区别
在操作对象时,“”是用在比较两个参考名称是否参考到同一对象,“equals()”是比较两个对象实际的内含值是否相同,打个比方就是“==”是比较两个标签是否绑在了同一件 衣服上,有的衣服完全一样但并不是同一件;“equals()”是比较这两件衣服是不是一样的
基本类型打包
- 打包器:Long、Ingeter、Double、Float、Boolean
- 打包基本类型:Integer wrapper1 = new Integer(data1);//把data1的内容打包到wrapper1里了
- 自动装箱拆箱:例如:
Integer wrapper = 10;//自动将信息装入wrapper
int foo = wrapper;//自动拆箱,将wrapper里的信息拿出来给foo
数组对象
•数组在java中是对象
•索引由0开始,若超出索引范围,则会抛出ArrayIndexOutOfBoundsException错误
public class Score
{
public static void main(String[] args)
{
int[] scores={88,81,74,68,78,76,77,85,95,93};
for(int i=0;i<scores.length;i++)
{
System.out.printf("学生分数:%d %n",scores[i]);
}
}
}
运行结果:
- 采用增强式for循环:
for(int score : score){
System.out.printf("学生分数:%d%n",score);
}
•声明二维数组:
int[][]cords = {
{1,2,3},
{4,5,6}
};//声明二维数组并赋初始值
for(int x = 0;x < cords.length;x++){ //得知有几列
for(int y = 0;y < cords[x].length;y++){ //取得每列的长度
System.out.printf("%2d",cords[x][y]); //指定列、行索引取得数组元素
}
}
- System.arraycopy()与Arrays.copyOf()
System.arraycopy()与Arrays.copyOf()都是可以进行数组的复制,但都是执行浅层复制,并没有实际复制出对象,若要连同对象一起复制,需自行操作
System.arraycopy()用法:System.arraycopy(来源数组,来源起始索引,目的数组,目的起始索引,复制长度);
Arrays.copyOf()用法:int score = Arrays.copyOf(来源数组,新数组长度); - 浅拷贝与深拷贝:
浅拷贝:并不是将对象复制到新的索引处,而是将来源数组里面的内容给新数组参考
深拷贝:将来源数组里面的内容复制给新数组
举例:就像是一本书,浅拷贝是两个人一起看,深拷贝是第二个人将第一个人的书进行复印,之后两个人每个人都有一本书,而且这两本书的内容一样
字符串对象
- String:字符串常量,字符串长度不可变
- StringBuilder:字符串累加,字符串长度可变(用法:builder.append(i).append('+');)
- StringBuffer:处理同步问题,在多线程环境下使用,让对象自行管理同步问题
- 字符串的本质是打包字符数组的对象,是java.lang.String类的实例。length()是取得字符串长度,charAt()是取得字符串中某个字符,toUpperCase()是将原本小写的字符串内容转为大写的字符串内容。
查询API文档
p87页代码:
public class TestJavaClass {
public static void main(String[] args) {
p87TestFloatEquals();
}
public static void p87TestFloatEquals() {
double a = 0.1;
double b = 0.1;
double c = 0.1;
if ((a+b+c) == 0.3){
System.out.println("等于0.3");
} else {
System.out.println("不等于0.3");
}
}
}
运行结果:
教材第五章内容总结
封装
封装的目的:隐藏对象细节,将对象当作黑箱进行操作
- 封装对象初始流程:构造函数
优点:不用重复撰写对象初始化流程 - 封装对象操作流程:定义方法
优点:对象可以自己处理相关数据 - 封装对象内部数据:使用private关键字定义,并提供取值方法成员
优点:用户无法知道、更改类中的私有数据
类语法细节
- public
如果想在其他包的 类程序代码中存取某包的类或对象成员,则该类或对象成员必须是公开成员,在Java中要使用public加以声明
可声明:公开类、公用构造函数、公开方法 - 构造函数与方法重载
构造函数:与类名称同名,无须声明返回类型的方法
如果定义类时,没有撰写任何构造函数,编译程序会自动加入一个无参数、内容为空的构造函数,如果自行编写了构造函数,编译程序就不会自动建立默认构造函数
重载构造函数:定义多个构造函数,只要参数类型或个数不同
重载定义方法:可为类似功能的方法提供统一名称,根据参数类型或个数的不同调用对应的方法
返回值不可作为方法重载的依据,可能会出现返回值类型不同但是返回值相同的情况,此时编译程序会将两个方法重载视为重复定义而编译失败 - this、final、static
this:在java中,this()代表了调用另一个构造函数,至于调用哪个构造函数,则是调用this()时给的自变量类型与个数而定
this()调用只能出现在构造函数的第一行
final:如果局部变量声明了final,表示设值后不能再变动,对象数据成员上也可以声明final
如果对象数据成员被声明为final,但没有明确使用 = 指定值,则表示延迟对象成员值的指定,在构造函数执行流程中,一定要有对该数据成员指定值的动作,否则编译错误
static:被声明为static的成员,不会让个别对象拥有,而是属于类
被声明为static的方法,可通过类名称与“.”运算符来调用static方法
如果有些动作想在位码加载后执行,则可定义static区块
在static区块不能出现this关键字 - 不定长度自变量
要使用不定长度自变量,声明参数列时要在类型关键字后面加上...
使用不定长度自变量时,方法上声明的不定长度参数必须是参数列最后一个 - 内部类
内部类:可以在类中再定义类
内部类本身可以存取外部类的成员
通常非静态内部类会声明为private
一个被声明为static的内部类,通常是将外部类当作名称空间,可以存取外部类static成员,但不可存取外部类非static成员 - 传值调用
Java中只有传值调用
教材学习中的问题和解决过程
- java的面向对象的思想和c有很大的区别。
- 比如字符串就是对象,是java.lang.String类别的一个实例
String text = "Have a nice day!! :)";
System.out.println("原文:" + text);
//传回全为大写的字符串内容
System.out.println("大写:" + text.toUpperCase());
//转回全为小写的字符串内容
System.out.println("小写:" + text.toLowerCase());
//计算字符串长度
System.out.println("长度:" + text.length());
//传回取代文字后的字符串
System.out.println("取代:" + text.replaceAll("nice", "good"));
//传回指定位置后的子字符串
System.out.println("子字符串:" + text.substring(5));
动手实践了一下教材的费氏数练习题~
import java.util.Scanner;
public class Fibonacci {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n;
Integer[] f = new Integer[100];
f[0] = new Integer(0);
f[1] = new Integer(1);
System.out.print("求几个费式数?");
n = Integer.parseInt(scanner.next());
if(n == 0||n == 1){
System.out.printf("%d",n);
}
else if(n > 1){
for(int i = 0;i < n;i++){
if(i > 1) {
f[i] = f[i - 1] + f[i - 2];
}
System.out.printf("%3d",f[i]);
}
}
}
}
代码调试中的问题和解决过程
需要注意的是:文档中的主文档名必须与公开类名称一致
使用class关键字定义类,在Field.java中定义了两个类,一个是非公开的Clothes类,另一个是公开(public)的Field类。
Clothes类中定义了color和size两个变量,叫作定义两个值域成员或定义两个数据对象成员。Clothes sun = new Clothes()为将sun名称参考至新建对象,
其中Clothes sun叫作声明参考名称、参考变量或直接叫参考,=是指定,new关键字是建立对象实例。
有几个类就会产生几个.class文档。
其他
一个类XXXX写到一个XXXX.java的习惯
public class XXXX{}
尽量不要在一个类中写多个class,如果有多个class,也只能有一个类前面加public
一个XXXX.java要有一个包含main函数的XXXXTester.java的测试类
构造方法决定类生成对象的方式
- this
new
封装 = 类 + 访问控制(public,protected,private...)
一个工程只能有一个main函数入口
注意类的作用域不能重复
感觉这两章的内容很多,学完之后结合代码理解会更深入一些。明白了类、对象、封装之后,OOP编程就基本上算是入门了。和C面向过程的思想不一样,虽然很多基本语法是一样的。
OOP的三大特性:封装,继承,多态
- 所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
- 后面的几章主要会针对继承和多态进行讲解。沿着OOP三大基本特性的路子,可以逐渐深入地掌握Java。
代码托管链接
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第二周 | 200/400 | 1/3 | 12/52 | |
预备作业 | 0/400 | 1/4 | 15/67 | |
第三周 | 500/900 | 1/5 | 10/77 |