文章目录
- 参考资料
- 1. 面向过程与面向对象
- 2. 基本元素:类和对象
- 2.1 类(class)和对象(object)是面向对象的核心概念
- 2.2 类及类的成员
- 2.3 类的语法格式
- 2.4 创建自定义类步骤
- 3. 对象的创建和使用
- 3.1 内存解析
- 3.2 [匿名对象]
- 4. 类的成员之一:属性(filed)
- 4.1 语法格式
- 4.2 变量的分类
- 4.3 成员变量(属性)与局部变量的区别
- 4.4 成员变量与局部变量的内存位置
- 4.4 对象属性的默认初始化赋值
- 5. 类的成员之二:方法(method)
- 5.1 方法概念
- 5.2 方法的声明格式
- 5.3 练习(着重注意对象数组)
- 5.4 对象数组的内存解析
- 5.5 方法的重载(overload)
- 5.6 可变个数的形参
- 5.7 方法参数的 值传递 机制(重点)
- 5.7.1 基本数据类型参数传递
- 5.7.2 引用数据类型参数传递
- 练习
- 5.8 递归(recursion)方法
- 6. 面向对象特征之一:封装和隐藏
- 6.1 四种权限修饰符
- 7. 类的成员之三:构造器(构造方法)
- 7.1 构造器的特征
- 7.2 构造器的作用
- 7.3 构造器创建
- 7.4 构造器重载
- 7.5 总结:属性赋值的过程
- 7.6 扩展知识:JavaBean
- 7.7 扩展知识:UML类图
- 8. 关键字:this
- 8.1 this理解
- 8.2 this 调用属性、方法、构造器
- 9. 关键字:package,import
- 9.1 package 关键字的使用
- 9.2 MVC 设计模式
- 9.3 JDK 中主要的包介绍
- 9.4 import关键字的使用
- 10. 练习
参考资料
1. 面向过程与面向对象
- 面向过程(POP) 与面向对象(OOP)
- 面向对象:Object Oriented Programming
- 面向过程:Procedure Oriented Programming
- 两者都是一种思想,面向对象是相对于面向过程而言的。
- 面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。
- 面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
- 面向对象更加强调运用人类再日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。
- 面向对象的三大特征
- 封装(Encapsulation)
- 继承(Inhertance)
- 多态(Polymorphism)
- 面向对象的思想概述
程序员从面向过程的执行者转化成了面向对象的指挥者
面向对象分析方法分析问题的思路和步骤:
- 根据问题需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
2. 基本元素:类和对象
2.1 类(class)和对象(object)是面向对象的核心概念
- 类是对一类事物的描述,是抽象的、概念上的定义;
- 对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。
2.2 类及类的成员
常见的类的成员有:
- 属性:对应类中的成员变量
- 行为:对应类中的成员方法
2.3 类的语法格式
public class Person{
private int age; //声明私有变量age
public void showAge(int i) {//声明方法showAge()
age = i;
}
}
2.4 创建自定义类步骤
3. 对象的创建和使用
- 创建对象语法:
类名 对象名 = new 类名();
- 使用
对象名.对象成员
的方式访问对象成员(包括属性和方法) - 类和对象的使用步骤(面向对象思想落地的实现)
- 1.创建类,设计类的成员
- 2.创建类的对象
- 3.通过“对象.属性”或“对象.方法”调用对象的结构
- 如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非 static 的),意味着:如果我们修改一个对象的属性 a,则不影响另外一个对象属性 a 的值。
package pers.chh3213.classLearn;
public class ClassTest {
public static void main(String[] args) {
Student stu = new Student();
Student stu2 = new Student();
stu.name = "John";
stu.age = 10;
stu.major="math";
stu.interests="play tennis";
stu.say();
stu2.age=12;
stu2.major="math";
stu2.name="Tom";
stu2.interests="play table tennis";
stu2.say();
}
}
class Student{
int age; //声明私有变量age
String name;
String major;
String interests;
public void say() {//声明方法showAge()
System.out.println("name:"+"\t"+name);
System.out.println("age:"+"\t"+age);
System.out.println("major:"+"\t"+major);
System.out.println("interests:"+"\t"+interests);
}
}
3.1 内存解析
- 堆(Heap),此内存区域的唯一目的就是
存放对象实例
,几乎所有的对象实例都在这里分配内存。这一点在 Java 虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。 - 通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于存储
局部变量
等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。 - 方法区(MethodArea),用于存储已被虚拟机加载的
类信息、常量、静态变量、即时编译器编译后的代码
等数据。
此部分可结合之前数组篇章的内存简析理解。
- 示例
3.2 匿名对象
- 匿名对象:没有名字的对象
- 匿名对象的特征:
- 语法上: 只创建对象,但是不用变量来接收
- 匿名对象的使用:
1. 匿名对象也是一个对象,具有对象的所有功能
2. 每一次使用匿名对象时,都是一个新的对象, 每次创建匿名对象都是不同的对象,一个匿名对象,只能使用一次,即匿名对象只能调用一次
- 匿名对象只在堆内存中开辟空间,而不存在栈内存的引用
- 使用情况
- 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
- 通常将匿名对象作为实参传递给一个方法调用。
- 示例:
public class NiMingObject {
public static void main(String[] args) {
//1.非匿名对象(正常的对象)
Dog d = new Dog();
d.setAge(10);
d.setName("来福");
//d.eat();
System.out.println(d.getAge()+"..."+d.getName());
//2.匿名对象
new Dog();
//3.匿名对象的使用
new Dog().setAge(18);
new Dog().setName("旺财");
System.out.println(new Dog().getAge()+"..."+new Dog().getName());
//new Dog().eat();
}
}
4. 类的成员之一:属性(filed)
4.1 语法格式
4.2 变量的分类
4.3 成员变量(属性)与局部变量的区别
4.4 成员变量与局部变量的内存位置
4.4 对象属性的默认初始化赋值
当一个对象被创建时,会对其中各种类型的成员变量紫红进行初始化赋值。
5. 类的成员之二:方法(method)
5.1 方法概念
- 方法是类或者对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或者过程。
- 将功能封装为方法的目的是:可以实现代码重用,简化代码。
- java中的方法不能独立存在,所有的方法必须定义在类里。
5.2 方法的声明格式
- 注意
- 没有具体返回值的情况,返回值类型用关键字
void
表示,那么方法体中可以不必使用return
语句,如果使用,仅用来结束方法。- 方法中只能调用方法或者属性,
不可以在方法内部定义方法
。
5.3 练习(着重注意对象数组)
利用面向对象的编程方法,设计类Circle计算圆的面积。
package pers.chh3213.classLearn;
public class CircleArea {
public static void main(String[] args) {
Circle circle = new Circle();
circle.setRadius(10.0);
double area = circle.computeArea();
System.out.println(area);
}
}
class Circle{
double radius;
public void setRadius(double r) {
radius = r;
}
public double computeArea() {
return(Math.PI*Math.pow(radius,2));
}
}
对象数组题目:
定义类Student,包含三个属性:
学号number(int),年级state(int),成绩score(int)。
创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
提示:
- 生成随机数:Math.random(),返回值类型double;
- 四舍五入取整:Math.round(double d),返回值类型long。
package pers.chh3213.classLearn;
public class StudentTest {
public static void main(String[] args) {
Student[] stu_arr = new Student[20];
for (int i = 0; i < stu_arr.length; i++) {
stu_arr[i] = new Student();
stu_arr[i].number= i+1;
// System.out.print(stu_arr[i].number+"\t");
}
//print information
for (int i = 0; i < stu_arr.length; i++) {
if(stu_arr[i].state==3) {
System.out.print("state 3:\t");
stu_arr[i].printInfor();
}
}
//sort
System.out.println("before sort");
for (int i = 0; i < stu_arr.length; i++) {
stu_arr[i].printInfor();
}
for (int i = 0; i < stu_arr.length-1; i++) {
for (int j = 0; j < stu_arr.length-1-i; j++) {
if(stu_arr[j].score>stu_arr[j+1].score) {
Student tempStudent = stu_arr[j];//如果需要换序,交换的是数组的元素,即Student对象
stu_arr[j]=stu_arr[j+1];
stu_arr[j+1]=tempStudent;
}
}
}
System.out.println("after sort");
for (int i = 0; i < stu_arr.length; i++) {
stu_arr[i].printInfor();
}
}
}
class Student{
int number;
int state = (int)(Math.random()*6)+1;
int score=(int)(Math.random()*100)+1;
public void printInfor() {
System.out.println("学号:" + number + ",年级:" + state + ",成绩:" + score);
}
}
5.4 对象数组的内存解析
5.5 方法的重载(overload)
- 定义:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。 - “两同一不同”:
同一个类、相同方法名;
参数列表不同:参数个数不同,参数类型不同 - 判断是否重载
与方法的返回值类型、权限修饰符、形参变量名、方法体都无关,只看参数列表。
- 练习
判断:与void show(int a,char b,double c){}构成重载的有:
a)void show(int x,char y,double z){} // no
b)int show(int a,double c,char b){} // yes
c) void show(int a,double c,char b){} // yes
d) boolean show(int c,char b){} // yes
e) void show(double c){} // yes
f) double show(int x,char y,double z){} // no
g) void shows(){double c} // no
5.6 可变个数的形参
JavaSE 5.0
中提供了Varargs(variable number of arguments)
机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。- 说明
jdk 5.0新增的内容
具体使用:
- 可变个数形参的格式:
数据类型 ...变量名
- 当调用可变个数形参的方法时,传入的参数的个数可以是:0个,1个,2个…
- 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载。
- 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。即二者不可共存。
- 可变个数形参在方法中的形参中,必须声明在末尾。
- 可变个数形参在方法中的形参中,最多只能声明一个可变形参。
public class MethodArgs {
public static void main(String[] args) {
MethodArgs test = new MethodArgs();
test.show("hell0");
test.show("hello","world");
// test.show();
test.show(new String[] { "AA", "BB", "CC" });
}
public void show(String s){
System.out.println("show(String): "+s);
}
public void show(String... strs) {
System.out.println("show(String ...strs)");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
}
// 此方法与show(String... strs) 不可共存
// public void show(String[] strs){
//
// }
public void show(int i, String... strs) {
}
}
5.7 方法参数的 值传递 机制(重点)
- 关于变量的赋值
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
- 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
- 形参:方法定义时,声明的小括号内的参数
- 实参:方法调用时,实际传递给形参的数据
java的实参值如何传入方法呢?
java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
5.7.1 基本数据类型参数传递
- 形参是基本数据类型:将实参基本数据类型变量的
数据值
传递给形参。
public class TransferTest1 {
public void swap(int a,int b){
int temp = a;
a = b;
b = temp;
System.out.println("swap方法里:a = "+a+"; b = "+b);
}
public static void main(String[] args) {
TransferTest1 test = new TransferTest1();
int a = 5;
int b = 10;
System.out.println("交换前:"+"a = " + a + ", b = " + b);
test.swap(a, b);
System.out.println("交换后:"+"a = " + a + ", b = " + b);
}
}
5.7.2 引用数据类型参数传递
- 形参是引用数据类型时,将实参引用数据类型变量的
地址值
传递给形参。
package pers.chh3213.classLearn;
public class TransferTest2 {
public static void main(String[] args) {
DataSwap dataSwap = new DataSwap();
dataSwap.a = 5;
dataSwap.b = 10;
System.out.println("交换前:"+"a = " + dataSwap.a + ", b = " + dataSwap.b);
swap(dataSwap);
System.out.println("交换后:"+"a = " + dataSwap.a + ", b = " + dataSwap.b);
}
public static void swap(DataSwap data) {
int temp = data.a;
data.a = data.b;
data.b = temp;
System.out.println("swap方法里:a = "+data.a+"; b = "+data.b);
}
}
class DataSwap{
public int a;
public int b;
}
练习
package pers.chh3213.classLearn;
public class transferTest {
public static void main(String[] args) {
int a=10;
int b=10;
method(a,b);
System.out.println("a="+a);
System.out.println("b="+b);
}
public static void method(int a,int b) {
a=a*10;
b=b*10;
System.out.println("a="+a);
System.out.println("b="+b);
System.exit(0);//此方法太过鸡贼,或者说此题太过鸡贼。
}
}
定义一个int型的数组:int[] arr = new int[]{12,3,3,34,56,77,432};
让数组的每个位置上的值去除以首位置的元素,得到的结果,作为该位置上的新值。遍历新的数组。
//错误写法
for(int i= 0;i < arr.length;i++){
arr[i] = arr[i] / arr[0];
}
//正确写法1
for(int i = arr.length –1;i >= 0;i--){
arr[i] = arr[i] / arr[0];
}
//正确写法2
int temp = arr[0];
for(int i= 0;i < arr.length;i++){
arr[i] = arr[i] / temp;
}
int[] arr = new int[10];
System.out.println(arr);//地址值?
char[] arr1 = new char[10];
System.out.println(arr1);//地址值?
int[] arr = new int[10];
System.out.println(arr);//地址值
char[] arr1 = new char[10];
System.out.println(arr1);//空数组,不打印出任何东西
int[] arr2 = new int[]{1,2,3};
//传进去的是一个Object的对象
System.out.println(arr2);//地址值
char[] arr3 = new char[]{'a','b','b'};
//传进去的是一个数组,里面遍历数据了
System.out.println(arr3);//abb
5.8 递归(recursion)方法
- 递归方法:一个方法体内调用它自身。
- 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
- 递归一定要向
已知方向
递归,否则这种递归就变成了无穷递归,类似于死循环。 - 练习
递归求阶乘(n!)的算法
package pers.chh3213.classLearn;
public class RecursionTest {
public static void main(String[] args) {
int result = nFactorial(3);
System.out.println(result);
}
public static int nFactorial(int number) {
if(number==1)return number;
else {
return number*nFactorial(number-1);
}
}
}
输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值
package pers.chh3213.classLearn;
public class RecursionTest {
public static void main(String[] args) {
int fibonacci_result = fibonacci(3);
System.out.println(fibonacci_result);
}
public static int fibonacci(int n) {
if(n==1 || n==2)return 1;
else {
return fibonacci(n-1)+fibonacci(n-2);
}
}
}
public class RecursionTest {
public static void main(String[] args) {
recursion(10);
}
private static int count = 0;
public static int recursion(int k) {
count++;
System.out.println("count:"+count+" k:"+k);
if(k<=0)return 0;
return recursion(k-1)+recursion(k-2);
}
}
6. 面向对象特征之一:封装和隐藏
- 设计追求“高内聚,低耦合”。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合:仅对外暴露少量的方法用于使用。
- 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
- 问题的引入:
当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。但除此之外,没有其他制约条件。但是,实际问题中,我们往往需要给属性赋值加入额外限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行条件的添加。同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的(private),此时,针对于属性就体现了封装性。
- 封装性的体现:
我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)。
隐藏一个类中不需要对外提供的实现细节;
使用者只能通过实现定制好的方法来访问数据,可以方便的加入控制逻辑,限制对属性的不合理操作;
便于修改,增强代码的可维护性。
6.1 四种权限修饰符
- Java 权限修饰符
public、protected、default(缺省)、private
置于类的成员
定义前,用来限定对象对该类成员的访问权限。 - 对于 class 的权限修饰只可以用
public
和default(缺省)
。public
类可以在任意地方被访问。default
类只可以被同一个包内部的类访问。
7. 类的成员之三:构造器(构造方法)
7.1 构造器的特征
- 具有与类相同 的名称
- 不声明返回值类型(与声明返回值类型为
void
不一样) - 不能被
static,final,synchronized,abstract,nativate
修饰,不能有return
语句返回值。
7.2 构造器的作用
- 创建对象
- 初始化对象的属性
7.3 构造器创建
- 语法格式
修饰符 类名(参数列表){
初始化语句;
}
- 根据参数不同,构造器可以分为如下两类:
- 隐式无参构造器(系统默认提供)
- 显式定义一个或多个构造器(无参、有参)
- 注意:
- Java语言中,每个类都至少有一个构造器
- 默认构造器的修饰符与所属类的修饰符一致
- 一旦显式定义了构造器,则系统不再提供默认构造器
- 一个类可以创建多个重载(Overload)的构造器
- 父类的构造器不可被子类继承,因此不能重写(Override)
- 练习
编写两个类,TriAngle 和 TriAngleTest,其中 TriAngle 类中声明私有的底边长 base 和高 height,同时声明公共方法访问私有变量。 此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
package pers.chh3213.classLearn;
public class TriAngleTest {
public static void main(String[] args) {
TriAngle triAngle = new TriAngle(10, 10);
triAngle.setBase(5);
triAngle.setHeight(10);
int s = triAngle.computeArea();
int s2 = triAngle.getBase()*triAngle.getHeight()/2;
System.out.println(s);
System.out.println(s2);
}
}
class TriAngle{
private int base;
private int height;
public int getHeight() {
return height;
}
public int getBase() {
return base;
}
public void setBase(int b) {
base = b;
}
public void setHeight(int h) {
height = h;
}
public TriAngle(int b,int h) {
// TODO Auto-generated constructor stub
height = h;
base = b;
}
public int computeArea() {
return base*height/2;
}
}
7.4 构造器重载
- 构造器一般用来创建对象的同时初始化对象
- 构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。
- 构造器重载,参数列表必须不同。
7.5 总结:属性赋值的过程
- 赋值的位置:
- 默认初始化
- 显式初始化
- 构造器中初始化
- 通过“对象属性“或“对象方法”的方式赋值
- 赋值的先后顺序:
①-②-③-④
7.6 扩展知识:JavaBean
- JavaBean是一种Java语言写成的可重用组件。
- 所谓JavaBean,是指符合如下标准的Java类:
- 类是公共的
- 有一个
无参的公共的
构造器 - 有属性,且有对应的
get
,set
方法
- 用户可以使用
JavaBean
将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包
,并且其他的开发者可以通过内部的JSP
页面、Servlet
、其他JavaBean
,applet
程序或者应用来使用这些对象。用户可以认为JavaBean
提供了一种随时随地的复制和粘贴
的功能,而不用关心任何改变。 - 示例
7.7 扩展知识:UML类图
-
+
表示 public 类型,-
表示 private 类型,#
表示 protected 类型 - 方法的写法:
方法的类型(+、-) 方法名(参数名:参数类型):返回值类型
8. 关键字:this
8.1 this理解
- 在Java中, this关键字比较难理解,它的作用和其词义很接近。
- 它在方法内部使用,即这个方法所属对象的引用;
- 它在构造器内部使用,表示该构造器正在初始化的对象。
- 通俗地说,this 理解为:当前对象,或当前正在创建的对象。
- this可以调用类的属性、方法和构造器
- 什么时候使用this关键字呢?
当在方法内需要用到调用该方法的对象时,就用this.
具体的:我们可以用this来区分属性
和局部变量
。
比如:this.name =name;
如果想直接在方法内返回当前对象:return this
8.2 this 调用属性、方法、构造器
- 在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,即
this.属性
或this.方法
增强程序的阅读性。不过,通常我们都习惯省略this.
- 当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加
this
来表明该变量是类的成员变量 - 使用
this
访问属性和方法时,如果在本类中未找到,会从父类中查找 this
调用构造器
- ① 我们可以在类的构造器中,显式的使用
this(形参列表)
的方式,调用本类中重载的其他的构造器! - ② 构造器中不能通过
this(形参列表)
的方式调用自己。 - ③ 如果一个类中声明了n个构造器,则最多有n -1个构造器中使用了
this(形参列表)
,因为自己不能调用自己。 - ④
this(形参列表)
必须声明在类的构造器的首行! - ⑤ 在类的一个构造器中,最多只能声明一个
this(形参列表)
。
- 示例
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(1);
System.out.println(p1.getAge());
p1.eat();
System.out.println();
Person p2 = new Person("jerry" ,20);
System.out.println(p2.getAge());
}
}
class Person{
private String name;
private int age;
public Person(){
this.eat();
String info = "Person 初始化";
System.out.println(info);
}
public Person(String name){
this();
this.name = name;
}
public Person(int age){
this();
this.age = age;
}
public Person(String name,int age){
this(age); //调用构造器的一种方式
this.name = name;
// this.age = age;
}
public void setNmea(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public void eat(){
System.out.println("人吃饭");
this.study();
}
public void study(){
System.out.println("学习");
}
}
- 练习
package pers.chh3213.classLearn;
public class BoyOrGirl {
public static void main(String[] args) {
Boy b1 = new Boy("John", 25);
Boy b2 = new Boy("Johnson", 24);
Girl g1 = new Girl("Jane", 23);
Girl g2 = new Girl("Angel", 22);
g1.compare(g2);
g1.marry(b2);
b1.marry(g2);
}
}
class Boy{
private String name;
private int age;
public Boy(String name,int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void marry(Girl girl) {
System.out.println(this.getName()+" married with:" +girl.getName());
}
public void shout() {
System.out.println("I'm a rich boy!!");
}
}
class Girl{
private String name;
private int age;
public Girl(String name,int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void marry(Boy boy) {
System.out.println(this.getName()+" married with:" +boy.getName());
}
public void compare(Girl girl) {
System.out.println(this.getName()+"'s age:"+ this.age);
System.out.println(girl.getName()+"'s age:"+ girl.getAge());
}
}
9. 关键字:package,import
- package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。它的格式为:
package顶层包名.子包名;
9.1 package 关键字的使用
- 1.为了更好的实现项目中类的管理,提供包的概念
- 2.使用 package 声明类或接口所属的包,声明在源文件的首行
- 3.包,属于标识符,遵循标识符的命名规则、规范(见名知意)
- 4.每
.
一次,就代表一层文件目录。 - 5.补充:同一个包下,不能命名同名接口或同名类;不同包下,可以命名同名的接口、类。
9.2 MVC 设计模式
- MVC 是常用的设计模式之一,将整个程序分为三个层次:
视图模型层
,控制器层
,数据模型层
。这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。
9.3 JDK 中主要的包介绍
1.java.lang----包含一些 Java 语言的核心类,如 String、Math、Integer、System 和 Thread,提供常用功能
2.java.net----包含执行与网络相关的操作的类和接口。
3.java.io----包含能提供多种输入/输出功能的类。
4.java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
5.java.text----包含了一些 java 格式化相关的类
6.java.sql----包含了 java 进行 JDBC 数据库编程的相关类/接口
7.java.awt----包含了构成抽象窗口工具集(abstractwindowtoolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。B/S C/S
9.4 import关键字的使用
- 为使用定义在
不同包
中的Java类,需用import
语句来引入指定包层次下所需要的类或全部类(*), import语句告诉编译器到哪里去寻找类。 - 语法格式:
import 包名.类名
- 注意:
- 在源文件中使用
import
显式的导入指定包下的类或接口; - 声明在
包
的声明和类
的声明之间; - 如果需要导入多个类或接口,那么就并列显式多个import语句即可;
- 举例:可以使用
java.util.*
的方式,一次性导入util包下所有的类或接口; - 如果导入的类或接口是
java.lang
包下的,或者是当前包下的,则可以省略此import语句; - 如果在代码中使用
不同包
下的同名
的类。那么就需要使用类的全类名
的方式指明调用的是哪个类; - 如果已经导入
java.a
包下的类。那么如果需要使用a
包的子包下的类的话,仍然需要导入; -
import static
组合的使用:调用指定类或接口下的静态的属性或方法。
10. 练习
1、写一个名为Account的类模拟账户。该类的属性和方法如下图所示。
该类包括的属性:
账号id,余额balance,年利率annuallnterestRate;
包含的方法:访问器方法(getter和setter方法),取款方法withdraw(),存款方法deposit()。提示:在提款方法withdraw中,需要判断用户余额是否能够满足提款数额的要求,如果不 能,应给出提示。
package pers.chh3213.classLearn;
/**
* 写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性:
账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter
方法),取款方法 withdraw(),存款方法 deposit()。
*
*/
public class Account {
private int id;
private double balance;
private double annualInterestRate;
public Account (int id, double balance, double annualInterestRate ) {
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
}
public int getId() {
return this.id;
}
public double getBalance() {
return this.balance ;
}
public double getAnnualInterestRate() {
return this.annualInterestRate ;
}
public void setId( int id) {
this.id = id;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
public void withdraw (double amount){
//取钱
if(amount>this.balance) {
System.out.println("pool guy!not enough money!");
}else {
this.balance = this.balance-amount;
System.out.println("you have withdrawen your money: "+amount);
System.out.println("now your balance is :" + balance);
}
}
public void deposit (double amount){//存钱
this.balance = this.balance + amount;
System.out.println("deposit success!your balance is: "+ this.balance);
}
}
2.创建 Customer 类
a.声明三个私有对象属性: firstName, lastName和account
b.声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f和I)
c.声明两个公有存取器来访问该对象属性,方法getFirstName和getLastName返回相应的属性。
d.声明setAccount方法来对account属性赋值。
e.声明getAccount方法以获取account属性。
package pers.chh3213.classLearn;
public class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String f,String l) {
this.firstName=f;
this.lastName =l;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Account getAccount() {
return this.account;
}
public void setAccount(Account account) {
this.account = account;
}
public void printAcount() {
System.out.println("Customer ["+this.firstName+this.lastName+"]"+"has a acount: id is:"+this.account.getId()+"annualInterestRate is "+this.account.getAnnualInterestRate()+"%, "+"balance is "+this.account.getBalance());
}
}
package pers.chh3213.classLearn;
import pers.chh3213.classLearn.Account;
public class MainClass {
public static void main(String[] args) {
Customer customer = new Customer("Jane", "Smith");
Account account = new Account(1000, 2000, 1.23);
customer.setAccount(account);
Account acount2 = customer.getAccount();
acount2.deposit(100);
acount2.withdraw(960);
acount2.withdraw(2000);
customer.printAcount();
}
}
addCustomer
方法必须依照参数(姓,名)构造一个新的Customer
对象,然后把它放到customer
数组中。还必须把numberOfCustomer
属性的值加1。getNumOfCustomers
方法返回numberofCustomers
属性值。
getCustomer 方法返回与给出的 index 参数相关的客户。
package pers.chh3213.classLearn;
public class Bank {
private Customer[] customers;
private int numberOfCustomer;
public Bank() {
this.customers = new Customer[1000];
}
public void addCustomer(String f,String l) {
Customer customer = new Customer(f, l);
this.customers[this.numberOfCustomer]=customer;
this.numberOfCustomer++;
}
public int getNumOfCustomers() {
return this.numberOfCustomer;
}
public Customer getCustomer(int index) {
return this.customers[index];
}
}
BankTest
package pers.chh3213.classLearn;
public class BankTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("jane", "Smith");
bank.addCustomer("Well", "Green");
bank.getCustomer(0).setAccount(new Account(50000));
bank.getCustomer(0).getAccount().withdraw(5000);
double balance = bank.getCustomer(0).getAccount().getBalance();
System.out.println("Customer: " + bank.getCustomer(0).getFirstName() + "'s balance:" + balance);
System.out.println("***************************");
bank.addCustomer("John", "Snow");
System.out.println("number of customers: " + bank.getNumOfCustomers());
}
}
练习:写出结果
class Demo{
public static void main(String[] args){
show(0);
show(1);
}
public static void show(int i){
switch(i){
default:
i+=2;
// System.out.println("1");
case 1:
i+=1;
// System.out.println("2");
case 4:
i+=8;
// System.out.println("3");
case 2:
i+=4;
// System.out.println("4");
}
System.out.println("i="+i);
}
}
}
i=15
i=14
Java的内存管理之垃圾回收
分配:由JVM自动为其分配相应的内存空间
释放:由JVM提供垃圾回收机制自动的释放内存空间
垃圾回收机制(GC:Garbage Collection):将垃圾对象所占用的堆内存进行回收。Java的垃圾回收机制是JVM提供的能力,由单独的系统级垃圾回收线程在空闲时间以不定时的方式动态回收。
垃圾对象:不再被任何引用指向的对象。
面试题:
问:在程序中是否可以通知垃圾回收机制过来回收垃圾?
能,通过调用System.gc();或Runtime.getRuntime().gc();
再问:调用了System.gc();或Runtime.getRuntime().gc();后是立刻执行垃圾回收吗?
不是,该调用并不会立刻启动垃圾回收机制开始回收,但会加快垃圾回收机制的运行。
package pers.chh3213.classLearn;
public class TestGC{
public static void main(String[] args)throws Exception{
for(int i=0; i<10; i++){
MyClass m = new MyClass();//这里本次循环完,本次创建的对象就成为垃圾了
System.out.println("创建第" + (i+1) + "的对象:" + m);
}
//通知垃圾回收机制来收集垃圾
System.gc();
//为了延缓程序结束
for(int i=0; i<10; i++){
Thread.sleep(1);
System.out.println("程序在继续....");
}
}
}
class MyClass{
//这个方法是垃圾回收机制在回收它的对象时,自动调用,理解成对象留临终遗言的方法
public void finalize(){
System.out.println("轻轻的我走了.....");
}
}
关于参数传递
package pers.chh3213.classLearn;
class Value{
int i = 15;
}
class Test{
public static void main(String argv[]) {
Test t = new Test();
t.first();
}
public void first() {
int i = 5;
Value v = new Value();
v.i = 25;
second(v, i);
System.out.println(v.i);
}
public void second(Value v, int i) {
i = 0;
v.i = 20;
Value val = new Value();
v = val;
System.out.print(v.i + " " + i+" ");
}
}
答案是:15 0 20
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的