前言:Java面对对象学习的三条主线
- Java类及类的成员:属性、方法、构造器;代码块、内部类;
- 面向对象的三大特征:封装性、继承性、多态性(、抽样性);
- 其他关键字:this、super、final、abstract、interface、package、import等。
三条主线并行推进
面向过程与面向对象
面向过程与面向对象区别
面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
面向对象:将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
面对对象的三大特征
封装(Encapsulation)
继承(Inheritance)
多态(Polymorphism)
面对对象的思想概述
程序员从面向过程的执行者转化成了面向对象的指挥者。
面对对象分析问题的思路和步骤:
- 根据问题需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象,对象是计算机世界中解决问题的最终工具。
Java基本元素:类和对象
面对对象的思想概述
类(Class)和对象(Object)是面向对象的核心概念。
- 类是对一类事物的描述,是抽象的、概念上的定义
- 对象是实际存在的该类事物的每个个体,因而也称为实例(instance)
万物皆对象
- 面对对象程序设计的重点是类的设计
- 类的设计,其实就是类的成员的设计
Java类及类的成员
现实世界的生物体,大到鲸鱼,小到蚂蚁,都是由最基本的细胞构成的。同理,Java代码世界是由诸多不同功能的类构成的。
现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质……那么,Java中用类来描述事物也是如此。常见类的成员有:
- 属性:对应类中的成员变量
- 行为:对应类中的成员方法
Field = 属性 = 成员变量 = 域、字段,Method = (成员)方法 = 函数
创建类的对象 = 类的实例化 = 实例化类
对象的创建和使用
面对对象思想落地的实现
package io.github.dawn333.oop; |
- 运行结果
内存解析
堆(heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
通常所说的栈(stack),是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(bolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。
方法区(method area),用于存储已被虚拟机加载类信息、常量、静态变量、即时编译器编译后的代码等数据。
对象内存解析
内存解析的说明
引用类型的变量,只可能存储两类值:null或地址值(含变量的类型)
对象数组的内存解析
JVM内存结构
- 关注书籍:《JVM规范》
- 虚拟机栈即为平时提到的栈结构,我们将局部变量存储在栈结构中。
- 堆,我们将new出来的结构(比如数组、对象)加载在堆空间中。补充:对象的属性(非static)加载在堆空间中。
理解“万事万物皆对象”
- 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构。
- Scanner,String等
- 文件:File
- 网络资源:URL
- 涉及到Java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。
匿名对象的使用
理解:我们创建的对象没有显示的赋给一个变量名, 即为匿名对象。
特征:匿名对象只能代用一次。
使用:如下:
package io.github.triabin.oop;
/**
*
* @Description 匿名对象的使用
* @author DawnLee
* @version 1.0
* @data 2020-8-6 16:04:02
*
*/
public class InstanceTest {
public static void main(String[] args) {
Phone p = new Phone();
System.out.println("正常调用:");
p.sendEmail();
p.playGame();
//匿名
System.out.println("\n匿名对象:");
new Phone().sendEmail();
new Phone().playGame();
System.out.println("\n匿名对象只能代用一次:");
new Phone().price = 1999;
new Phone().showPrice();
System.out.println("\n匿名对象的使用:");
PhoneMall mall = new PhoneMall();
// mall.show(p);
mall.show(new Phone());
}
}
class PhoneMall{
public void show(Phone phone) {
phone.sendEmail();
phone.playGame();
}
}
class Phone{
double price;//价格
public void sendEmail() {
System.out.println("发送邮件");
}
public void playGame() {
System.out.println("玩游戏");
}
public void showPrice() {
System.out.println("手机的价格为:" + price);
}
}- 运行结果
类的成员之一:属性
类中属性的使用
属性(成员变量)与局部变量区别
相同点
- 定义变量的格式:数据类型 变量名 = 变量值
- 先声明,后使用
- 变量都有其对应的作用域
不同点
在类中声明的位置不同:
- 属性:直接定义在类的一对{}内
- 局部变量:声明在方法内、方法形参、构造器形参、构造器内部的变量
关于权限修饰符
- 属性:可以在声明属性时,指明其权限,使用权限修饰符,常用的权限修饰符有:private、public、缺省、protected —》讲封装性时再说,目前缺省即可。
- 局部变量:不可以使用权限修饰符。
默认初始化值的情况
- 属性:类的属性,根据其类型,都有默认初始化值。
- 整形(byte、short、int、long):0
- 浮点型(float、double):0.0
- 字符型(char):0(或’\u0000’)
- 布尔型(boolean):false
- 引用数据类型(类、数组、接口):null
- 局部变量:没有默认初始化值,意味着在调用局部变量之前一定要显示赋值。
- 特别地:形参在调用时,我们赋值即可,例如下列代码实例的User方法中的String language。
- 属性:类的属性,根据其类型,都有默认初始化值。
在内存中加载的位置
- 属性:加载到堆空间中(非static)
- 局部变量:加载到栈空间
变量的分类二:按照在类中声明的位置
代码实例:
package io.github.triabin.oop; |
类的成员之二:方法
- 方法:描述类具有的功能。比如:Math类:sqrt()\random()\……
- Scanner类:nextXxx()……
- Arrarys类:sort()\binarySearch()\toString()\equals()\……
类中方法的声明和使用
举例(后面的代码实例中):
- public void eat(){}(void:没有返回值)
- public void sleep(int hour){}
- public String getNmae() {}(String:返回一个String类型的数据)
- public String getNation(String nation){}
方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
- 注意:static、final、abstract来修饰的方法以后再讲。
说明:
关于权限修饰符:目前默认方法的权限修饰符先都使用public。
Java规定的4种权限修饰符:private、public、缺省、protected —> 封装性再细说.
返回值类型:有返回值or无返回值
如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中必须使用return关键字来返回指定类型的变量或常量。例如下列代码实例方法中的getName()方法。
如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不使用return。但是,如果使用的话,只能“return;”,表示结束此方法。
我们定义方法该不该有返回值?
①题目要求
②凭经验:具体问题具体分析
方法名:属于标识符,遵循表示符的规则和命名规范,“见名知意”。
形参列表:方法可以声明0个,1个或多个形参。
格式:数据类型1 形参1,数据类型2 形参2,…
我们定义方法时要不要形参?
① 题目要求
② 凭经验,具体问题具体分析
方法体:方法功能的体现。
return关键字的使用:
- 使用范围:使用在方法体中。
- 作用:①结束方法;②针对于有返回值的方法,使用“return 数据;”方法返回所要的数据。
- 注意:return关键字后面不可以声明执行语句。
方法的使用中可以调用当前类的属性或方法
- 特别地:方法A中调用方法A:递归方法。
- 方法中不能再定义方法。
代码实例
package io.github.triabin.oop; |
方法的分类(按照是否有形参及返回值)
无返回值 | 有返回值 | |
---|---|---|
无形参 | void方法名(){} | 返回值类型 方法名 (){} |
有形参 | void方法名(形参列表){} | 返回值类型 方法名 (形参列表){} |
练习题
练习一:创建一个Person类,其定义如下:
Person |
---|
name:String age:int sex:int |
+study():void +showAge():void +addAge(int i):int |
要求:
- 创建Person类的对象,设置该对象的name、age和sex属性,调用study()方法,输出字符串“studying”,调用showAge()方法显示age值,调用addAge()方法给对象的age属性增加2岁。
- 创建第2个对象,执行上述操作,体会同一个类的不同对象之间的关系。
Person类:
package io.github.triabin.oopexercise1; |
调用类:
package io.github.triabin.oopexercise1; |
- 运行结果
tips:在同一个包(package)里面,类方法可以分开写然后正常创建类的对象。
练习二
package io.github.triabin.oopexercise1; |
- 运行结果
练习三
package io.github.triabin.oopexercise1; |
- 3.1:
- 3.2
- 3.3
练习四
package io.github.triabin.oopexercise1; |
- 运行结果:
- 优化:将各个重复性操作封装成方法
package io.github.triabin.oopexercise1; |
Tips:面试遇到举例说明类和对象的关系时尽量举开发中的例子。
再谈方法
方法的重载
定义
- 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
- “两同一不同”:同一个类、相同的方法名;参数列表不同:参数个数不同、参数类型不同。
- 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
特点
- 与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
示例
- Arrays类中重载的sort() / binarySearch()
package io.github.triabin.methodagain;
/**
*
* @Description 方法重载举例
* @author DawnLee
* @version 1.0
* @data 2020-8-6 18:51:26
*
*/
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
test.getSum(1,2);
}
//如下4个方法构成了重载
public void getSum(int i,int j) {
System.out.println("1");
}
public void getSum(double d1, double d2) {
System.out.println("2");
}
public void getSum(String s, int i) {
System.out.println("3");
}
public void getSum(int i,String s) {
System.out.println("4");
}
// public int getSum(int i,int j) {
// return 0;
// }
// public void getSum(int m,int n) {
//
// }
}Tips:支持自动类型提升,例如,如果形参为double型,但是输入的形参为int型,则自动将int型转换为double型。
判断是否是重载
- 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系,只看形参数目和类型。
通过对象调用方法时,如何确定某一个指定的方法:
- 方法名 —> 参数列表
练习题
练习题一
- 编写程序,定义三个重载方法并调用。方法名为mOL。
- 三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果、相乘并输出结果、输出字符串信息。
- 在主类的main方法中分别用参数区别调用三个方法。
package io.github.triabin.methodagain; |
练习题二
- 定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方法求两个double值中的最大值,第三个方法求三个double值中的最大值,分别调用三个方法。
package io.github.triabin.methodagain; |
可变个数的形参
JavaSE 5.0中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。
JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a,String[] books);
JDK 5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a,String...books);
具体使用:
- 可变个数形参的格式:数据类型 … 变量名
- 当调用可变个数形参的方法时,传入的参数个数可以是:0个、1个、2个……
- 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载。
- 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不够成重载(即二者不能共存)。
- 可变个数形参在方法的形参列表中,必须声明在末尾。
- 可变个数形参在方法的形参列表中,最多只能声明一个可变形参。
示例
package io.github.triabin.methodagain;
/**
*
* @Description 可变个数的形参具体使用
* @author DawnLee
* @version 1.0
* @data 2020-8-6 20:29:02
*
*/
public class VarAgu {
public static void main(String[] args) {
VarAgu test = new VarAgu();
test.show(12);
test.show("Hello");
test.show("Hello","world");
test.show();
// test.show(new String[] {"AA","BB","CC"});//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量,JDK 5.0向前兼容,所以(String ... strs)同样可以用此方法传入形参
test.show("AA","BB","CC");
}
public void show(int i) {
System.out.println("show(int i)");
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(String ... strs) {
System.out.println("show(String ... strs)");
//调用
for(int i = 0;i < strs.length;i++) {
System.out.println(strs[i]);
}
}
// public void show(String[] strs) {//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
// System.out.println("show(String[] strs)");
// }
}- 运行结果
方法参数的值传递机制
变量的值传递机制
关于变量的赋值:
如果是基本数据类型,此时赋值的是变量所保存的数据值;
如果变量是引用数据类型,此时,赋值的是变量所保存的数据的地址值。
示例
package io.github.triabin.methodagain;
/**
*
* @Description 方法参数的值传递机制
* @author DawnLee
* @version 1.0
* @data 2020-8-6 21:03:46
*
*/
public class ValueTransfer {
public static void main(String[] args) {
System.out.println("******基本数据类型的值传递情况******");
int m = 10;
int n = m;
System.out.println("m = " + m + ", n = " + n);
n = 20;
System.out.println("m = " + m + ", n = " + n);
System.out.println("******引用数据类型的值传递情况******");
Order o1 = new Order();
o1.orderID = 1001;
Order o2 = o1;//赋值以后,o1和o2的地址值相同,都指向了堆空间中同一个对象实体。
System.out.println("o1.orderID = " + o1.orderID + ", o2.orderID = " + o2.orderID);
o2.orderID = 1002;
System.out.println("o1.orderID = " + o1.orderID + ", o2.orderID = " + o2.orderID);
}
}
class Order{
int orderID;
}- 运行结果
方法的形参传递机制:值传递
形参:方法定义时,声明的小括号内的参数。
实参:调用方法时实际传递给形参的数据。
值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值;
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
示例
package io.github.triabin.methodagain;
/**
*
* @Description 法的形参传递机制:值传递
* @author DawnLee
* @version 1.0
* @data 2020-8-6 21:52:21
*
*/
public class ValueTransfer01 {
public static void main(String[] args) {
int m = 10;
int n = 20;
System.out.println("m = " + m + ", n = " + n);
//交换两个变量值的操作
// int temp = m;
// m = n;
// n = temp;
ValueTransfer01 test = new ValueTransfer01();
test.swap(m, n);//未能交换,原因看内存解析。
System.out.println("m = " + m + ", n = " + n);
}
public void swap(int m,int n) {
int temp = m;
m = n;
n = temp;
}
}- 执行结果
- 内存解析(交换失败原因)
package io.github.triabin.methodagain;
public class ValueTransfer02 {
public static void main(String[] args) {
Data data = new Data();
data.m = 10;
data.n = 20;
System.out.println("m = " + data.m + ",n = " + data.n);
//交换m和n的值
// int temp = data.m;
// data.m = data.n;
// data.n = temp;
ValueTransfer02 test = new ValueTransfer02();
test.swap(data);
System.out.println("m = " + data.m + ",n = " + data.n);
}
public void swap(Data data) {
int temp = data.m;
data.m = data.n;
data.n = temp;
}
}
class Data{
int m;
int n;
}- 运行结果
- 内存解析
练习题
例题一:方法的参数传递
package io.github.triabin.methodagain; |
输出结果
15 0
20
内存解析
练习二
package io.github.triabin.methodagain; |
注意:本题不是考察方法的参数传递,只是一个易混淆思考方向的题目
练习三:将对象作为参数传递给方法
定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()返回圆的面积。
定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义如下:public void printAreas(Circle c, int time)
在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。例如,time为5,输出半径为1,2,3,4,5及其对应的圆面积。
在main方法中调用printAreas(),调用完毕后输出当前半径值。程序运行结果如图所示:
package io.github.triabin.methodagain;
/**
*
* @Description 值传递机制练习三
* @author DawnLee
* @version 1.0
* @data 2020-8-7 9:30:36
*
*/
public class ValueTransferEx03 {
public static void main(String[] args) {
PassObject test = new PassObject();
Circle c = new Circle();
int time = 5;
test.printAreas(c, time);
System.out.println("now radius is:" + c.radius);
}
}
class Circle{
double radius = 0;
public double findArea() {
return Math.PI * radius * radius;
}
}
class PassObject{
public void printAreas(Circle c,int time) {
System.out.println("Radius\t\tArea");
for(double i = 1;i <= time;i++) {
c.radius = i;
System.out.println(c.radius + "\t\t" + c.findArea());
}
c.radius = time + 1;
}
}- 运行结果
递归(recursion)方法
递归方法:一个方法体内调用自身。
方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无需循环控制。递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
示例
package io.github.triabin.methodagain;
/**
*
* @Description 递归方法示例
* @author DawnLee
* @version 1.0
* @data 2020-8-7 15:04:41
*
*/
public class RecursionIns {
public static void main(String[] args) {
//计算1-100内所有数的和
//方式一
int sum1 = 0;
for(int i = 1;i <= 100;i++) {
sum1 += i;
}
System.out.println("方式一:" + sum1);
//方式二(递归):
RecursionIns test = new RecursionIns();
int sum2 = test.getSum(100);
System.out.println("方式二:" + sum2);
//计算阶乘
int n = 5;
int fac = test.getFac(n);
System.out.println(n + "的阶乘为:" + fac);
}
//计算1-100内所有数的和的方法
public int getSum(int n) {
if(n == 1) {
return n;
}else {
return n + getSum(n - 1);
}
}
//计算1-n之间的乘积:n!
public int getFac(int n) {
if(n == 1) {
return n;
}else {
return n * getFac(n - 1);
}
}
}- 运行结果
练习题
练习一
- 已知有一个数列:f(0) = 1,f(1) = 4,f(n+2) = 2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。
package io.github.triabin.methodagain; |
- 运行结果
练习二:斐波那契数列(Fibonacci)
输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值1 1 2 3 5 8 13 21 34 55。
规律:一个数等于前两个数之和。
要求:计算斐波那契数列的第n个值,并将整个数列打印出来。
package io.github.triabin.methodagain; |
- 运行结果
章节练习
什么是方法重载?
“两同一不同”:同一个类、相同的方法名;参数列表不同。
说明Java方法中的参数传递机制的具体体现。
基本数据类型:数据值
引用数据类型:地址值(含变量的数据类型)例:
Person p1 = new Person();
User u1 = p1;//编译错误
成员变量和局部变量在声明的位置上是否有默认初始化值?
谈谈return关键字的使用。
①结束方法
②针对于有返回值的方法,return + 返回数据;
拓展:宋老师,我今天去百度面试,遇到一个双重递归调用的问题,我琢磨了一下,完全不知道为什么。打断点了,也还是没看懂程序为什么会那样走。您有空可以看一下,求指教。
/**
* 测试递归调用的次数
*/
public void binomial(){ recursion(10); }
private static int recursion(int k){
count++;
System.out.println("count1:" + count + " k:" + k);
if(k <= 0){
return 0;
}
return recursion(k - 1) + recursion(k - 2);//287
//return recursion(k - 1);//11
//return recursion(k - 1) + recursion(k - 1);//2047
}- 图解
OOP特征一:封装与隐藏
- OOP,即Object oriented programming,面向对象编程。
引入
- 为什么需要封装?封装的作用和含义?
- 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部结构吗?有必要碰电动机吗?
- 我要开车……
- 我们程序设计追求“高内聚,低耦合”。
- 高内聚:类的内部操作细节自己完成,不允许外部干涉;
- 低耦合:仅对外暴露少量的方法用于使用。
- 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
信息的封装和隐藏
当我们创建一个类的对象以后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值。这里,赋值的操作要受属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们需要给属性赋值加入额外的条件。这个条件就不能再属性声明时体现,我们只能通过方法进行限制条件的添加。(比如,示例中的setLegs()方法)同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的(private)。
–> 此时,针对属性就体现了封装性。
封装性的体现:我们讲类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值。
拓展:封装性的体现
①如上 ②不对外暴露的私有的方法 ③单例模式 …
示例
package top.triabin.encapsulationconcealment; |
- 运行
四种访问权限修饰符
- 封装性的体现,需要权限修饰符来配合
Java规定的种权限(从小到大排列):private、缺省、protected、public
Java的权限修饰符public、protected、private置于类的成员定义前,用来限定对象对该类成员的访问权限。
4种权限修饰符可以用来修饰类及类的内部结构:属性、方法、构造器、内部类。
具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类;修饰类只能用default(缺省)、public。
代码示例
同一个包不同的类里面
package top.triabin.encapsulationconcealment;
/**
*
* @Description 权限修饰符使用测试(同包不同类)
* @author DawnLee
* @version
* @data 2020-8-8 10:58:12
*
*/
public class PromissionInsTest {
public static void main(String[] args) {
PermissionIns order = new PermissionIns();
System.out.print(order.orderDefault + " ");
System.out.println(order.orderPublic);
//出了PromissionIns类以后,私有结构就不可以调用了。
// System.out.println(order.orderPrivate);//报错:The field PermissionIns.orderPrivate is not visible
//方法也类似
System.out.println();
order.methodDefault();
order.show();
order.methodPublic();
//出了PromissionIns类以后,私有结构就不可以调用了。
// order.methodPrivate;
order.show();
}
}同一个Project不同的包里面
package top.triabin.prossiontest;
import top.triabin.encapsulationconcealment.PermissionIns;
/**
*
* @Description 权限修饰符使用测试(不同的包)
* @author DawnLee
* @version 1.0
* @data 2020-8-8 11:43:11
*
*/
public class PromissionClassTest {
public static void main(String[] args) {
PermissionIns order = new PermissionIns();
System.out.println(order.orderPublic);
//出了PromissionIns类所属的包以后,私有结构、缺省声明的结构都不可以用了
// System.out.print(order.orderDefault + " ");
// System.out.println(order.orderPrivate);//报错:The field PermissionIns.orderPrivate is not visible
//方法也类似
System.out.println();
//出了PromissionIns类所属的包以后,私有结构、缺省声明的结构都不可以用了
// order.methodDefault();
order.show();
order.methodPublic();
//出了PromissionIns类以后,私有结构就不可以调用了。
// order.methodPrivate;
order.show();
}
}总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构的在被调用时的可见性大小。
章节练习
创建程序,在其中定义两个类:Person和PersonTest类。定义如下:用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。在PersonTest类中实例化Person类的对象b,调用setAge()和getAge()方法,体会Java的封装性。
Person |
---|
-age:int |
+setAge(i:int) +getAge():int |
package top.triabin.encapsulationconcealment; |
运行
类的成员之三:构造器(或构造方法)
构造器的作用
创建对象
初始化对象的信息
示例
package top.triabin.constructor;
/**
*
* @Description 类的结构之三:构造器(或构造方法、constructor)的使用
* @author DawnLee
* @version
* @data 2020-8-8 14:52:46
*
*/
public class PersonTest {
public static void main(String[] args) {
//创建类的对象:new + 构造器
Person p = new Person();
p.eat();
Person p1 = new Person("Tom");
System.out.println(p1.name);
}
}
class Person{
//属性
String name;
int age;
//构造器
public Person() {
System.out.println("Person()....");
}
public Person(String n) {
name = n;
}
//方法
public void eat() {
System.out.println("人吃饭");
}
public void study() {
System.out.println("人可以学习");
}
}- 运行
说明
- 如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器。
- 定义构造器的格式:权限修饰符 类名(形参列表){}。
- 一个类中定义多个构造器,彼此构成重载。
- 一旦我们显式定义了构造器之后,系统就不再提供默认的空参构造器。
- 一个类中,至少会有一个构造器。
练习
在前面定义的Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
//构造器
public Person(){
age = 18;
}修改上题中的类和构造器,增加name属性,使得每次创建Person对象的同时初始化对象的age属性值和name属性值。
Person -name:String +setName(i:String)
+getName():Stringpackage top.triabin.constructor;
/**
*
* @Description 练习题第2题
* @author DawnLee
* @version 1.0
* @data 2020-8-8 15:27:46
*
*/
public class PersonEx02 {
public static void main(String[] args) {
//创建类的对象:new + 构造器
Person p = new Person("Tom",21);
System.out.println("姓名:" + p.getName() + "\n年龄:" + p.age);
}
}
class Person{
private String name;
int age;
public Person(String n,int a) {
name = n;
age = a;
}
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
}- 运行
编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形面积。
在同一个包下,两个类分开创建。
- TriAngle类
package top.triabin.constructor;
/**
*
* @Description TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。此外,提供类必要的构造器。
* @author DawnLee
* @version
* @data 2020-8-8 15:43:13
*
*/
public class TriAngle {
private double base;
private double height;
public TriAngle() {
//开发时习惯上提供一个空参
}
public TriAngle(double b,double h) {
base = b;
height = h;
}
public void setBase(double b) {
base = b;
}
public double getBase() {
return base;
}
public void setHeight(double h) {
height = h;
}
public double getHeight() {
return height;
}
}- TriAngleTest类
package top.triabin.constructor;
/**
*
* @Description 另一个类中使用这些公共方法,计算三角形面积。
* @author DawnLee
* @version 1.0
* @data 2020-8-8 15:54:34
*
*/
public class TriAngleTest {
public static void main(String[] args) {
System.out.println("方式一:调用空参的构造器");
TriAngle t1 = new TriAngle();
t1.setBase(2.0);
t1.setHeight(2.4);
System.out.println("三角形的底边长为" + t1.getBase() + ",高为" + t1.getHeight() + ",所以面积为" + (t1.getBase() * t1.getHeight() / 2) + "。\n");
System.out.println("方式二:调用带参的构造器");
TriAngle t2 = new TriAngle(2.0,2.4);
System.out.println("三角形的底边长为" + t2.getBase() + ",高为" + t2.getHeight() + ",所以面积为" + (t2.getBase() * t2.getHeight() / 2) + "。\n");
}
}- 运行
定义Student类,有4个属性:String name、int age、String school、String major。定义Student类的3个构造器:
①第一个构造器Student(String n,int a)设置类的name和age属性;
②第二个构造器Student(String n,int a, String s)设置类的name,age和school属性;
③第三个构造器Student(String n,int a,String s,String m)设置类的name,age,school和major属性。
在main方法中分别调用不同的构造器创建对象,并输出器属性值。
package top.triabin.constructor;
/**
*
* @Description 课后练习三
* @author DawnLee
* @version 1.0
* @data 2020-8-8 18:35:25
*
*/
public class StudentEx03 {
public static void main(String[] args) {
Student s = new Student();
System.out.println("name:" + s.name + "\tage:" + s.age + "\tschool:" + s.school + "\tmajor:" + s.major);
Student s1 = new Student("Triabin",18);
System.out.println("name:" + s1.name + "\tage:" + s1.age + "\tschool:" + s1.school + "\tmajor:" + s1.major);
Student s2 = new Student("Triabin",18,"SUES");
System.out.println("name:" + s2.name + "\tage:" + s2.age + "\tschool:" + s2.school + "\tmajor:" + s2.major);
Student s3 = new Student("Triabin",18,"SUES","BTE");
System.out.println("name:" + s3.name + "\tage:" + s3.age + "\tschool:" + s3.school + "\tmajor:" + s3.major);
}
}
class Student{
String name;
int age;
String school;
String major;
public Student() {
//空参
}
public Student(String n,int a) {
name = n;
age = a;
}
public Student(String n,int a,String s) {
name = n;
age = a;
school = s;
}
public Student(String n,int a,String s,String m) {
name = n;
age = a;
school = s;
major = m;
}
}- 运行
总结:属性赋值的先后顺序
package top.triabin.constructor; |
扩展知识
扩展知识一:JavaBean
- JavaBean是一种Java语言写成的可重用组件。
- 所谓JavaBean,是指符合如下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
- 用户可以使用JavaBean将功能、处理。值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
扩展知识二:UML类图
+表示public类型,-表示private类型,#表示protected类型。
方法的写法:
方法的类型(+、-) 方法名(参数名:参数类型):返回值类型
关键字:this
this关键字的使用
this可以用来修饰:属性、方法、构造器。
this修饰属性和方法:this可理解为当前对象(方法中)或当前正在创建的对象(构造器中)
- 在类的方法中,我们可以使用“this.属性”或“this.方法”的方式,调用当前正在创建的对象属性或方法。但是通常情况下,我们都选择省略“this.”。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式地使用“this.变量”的方式,表明此变量是属性,而非形参。
- 在类的构造器中,我们可以使用“this.属性”或”this.方法“的方式,调用当前属性或方法。但是通常情况下,我们都选择省略”this.“。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式地使用“this.变量”的方式,表明此变量是属性,而非形参。、
this调用构造器
- 我们在类的构造器中,可以显式的使用“this(形参列表)”的方式,调用本类中指定的其他构造器。
- 构造器中不能通过“this(形参列表)”的方式调用自己。
- 如果有n个构造器,最多有n-1个个构造器中使用了“this(形参列表)”
- 规定:“this(形参列表)”必须声明在当前构造器的首行
- 构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他构造器。
示例
package top.triabin.keywordthis;
/**
*
* @Description this关键字的使用
* @author DawnLee
* @version 1.0
* @data 2020-8-8 19:47:08
*
*/
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(18);
System.out.println(p1.getAge());
Person p2 = new Person("Triabin",20);
System.out.println(p2.getAge() + "\t" + p2.getName());
}
}
class Person{
private String name;
private int age;
public Person() {
}
//构造器中使用:理解为当前正在创建的对象(Person)
public Person(String name) {
this.name = name;
}
public Person(int age) {
this.age = age;
}
public Person(String name,int age) {
// this(name);//调用其他构造器
// this.age = age;
this(name);
this.age = age;
}
//方法中使用:理解为当前对象(Person)
public void setName(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;
}
}
练习
练习一:添加必要的构造器,综合应用构造器的重载、this关键字。
Boy | Girl |
---|---|
-name:String -age:int |
-name:String -age:int |
+setName(i:String) +getName():String +setAge(i:int) +getAge():int +marry(girl:Girl) +shout():void |
+setName(i:String) +getName():String +marry(boy:Boy) +compare(girl:Girl) |
- Boy类
package top.triabin.keywordthis; |
- Girl类
package top.triabin.keywordthis; |
- 测试类
package top.triabin.keywordthis; |
- 运行
练习二:实验一
写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性:
账号 id,余 额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter
方法),取款方法 withdraw(),存款方法 deposit()。Account private int id
private double balance
private double annualInterestRatepublic Account (int id, double balance, double annualInterestRate ) public int getId()
public double getBalance()
public double getAnnualInterestRate()
public void setId( int id)
public void setBalance(double balance)
public void setAnnualInterestRate(double annualInterestRate)
public void withdraw (double amount)//取钱
public void deposit (double amount)//存钱- 提示:在提款方法 withdraw 中,需要判断用户余额是否能够满足提款数额的要求,如果不
能,应给出提示。
package top.triabin.keywordthis;
/**
*
* @Description 实验一类:Account
* @author DawnLee
* @version 1.0
* @data 2020-8-9 9:48:18
*
*/
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 id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public double getAnnualInterestRate() {
return annualInterestRate;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
public void withDraw(double amount) {//取钱
if(amount > this.balance) {
System.out.println("余额不足,取款失败!");
return;
}
this.balance -= amount;
System.out.println("成功取出:" + amount);
}
public void deposit(double amount) {//存钱
this.balance += amount;
System.out.println("成功存入:" + amount);
}
}- 提示:在提款方法 withdraw 中,需要判断用户余额是否能够满足提款数额的要求,如果不
创建Customer类。
Customer private String firstName
private String lastName
private Account accountpublic Customer(String f,String l) public String getFirstName()
public String getLastName()
public Account getAccount()
public void setAccount(Account account)- 声明三个私有对象属性:firstName、lastName 和 account。
- 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f和 l)。
- 声明两个公有存取器来访问该对象属性,方法getFirstName 和getLastName返回相应的属性。
- 声明 setAccount 方法来对 account 属性赋值。
- 声明 getAccount 方法以获取 account 属性。
package top.triabin.keywordthis;
/**
*
* @Description 实验一类:Customer
* @author DawnLee
* @version 1.0
* @data 2020-8-9 9:49:58
*
*/
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 firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}写一个测试程序。
(1)创建一个Customer,名字叫Jane Smith,他有一个账号为1000,余额为 2000 元,年利率为1.23%的账户。
(2)对Jane Smith操作。
- 存入100元,再取出960元。再取出2000元。
- 打印出Jane Smith的基本信息。
package top.triabin.keywordthis;
/**
*
* @Description 课后练习:实验一
* @author DawnLee
* @version 1.0
* @data 2020-8-9 9:45:58
*
*/
public class Experiment1Test {
public static void main(String[] args) {
Customer c = new Customer("Jane","Smith");
Account a = new Account(1000,2000,1.23);
a.deposit(100);
a.withDraw(960);
a.withDraw(2000);
System.out.println("Custmor [" + c.getFirstName() + "·" + c.getLastName() + "] has a account: id is " + a.getId() + ", \nannualInterestRate is " + a.getAnnualInterestRate() + "%, balance is " + a.getBalance());
}
}- 运行
练习三:实验二
按照如下的UML类图,创建相应的类,提供必要的的结构。
Account -balance:double +Account(init_balance:double) +getBalance():double
+deposit(amt:double)
+withdraw(amt:double)在提款方法withdraw()中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应该给出提示。deposit()方法表示存款。
package experiment2;
/**
*
* @Description this关键字课后练习:实验二类1--Account
* 初始化账户余额和存取钱
* @author DawnLee
* @version
* @data 2020-8-9 14:16:23
*
*/
public class Account {
private double balance;
public Account(double init_balance) {
balance = init_balance;
}
public double getBalance() {
return balance;
}
public void deposit(double amt) {//存钱
if(amt > 0) {
balance += amt;
System.out.println("\n成功存入:" + amt + "元。\n当前余额:" + balance + "元。");
}
}
public void withdraw(double amt) {
if(amt > balance) {
System.out.println("\n余额不足,取款失败!\n当前余额:" + balance + "元。");
return;
}
balance -= amt;
System.out.println("成功取出:" + amt + "元。\n当前余额:" + balance + "元。");
}
}按照如下的UML类图,创建相应的类,提供必要的结构。
Customer -firstName:String
-lastName:String
-account:Account+Customer(f:String,l:String) +getFirstName():String
+getLastName():String
+getAccount():Account
+setAccount(account:Account)package experiment2;
/**
*
* @Description this关键字课后练习:实验二类2--Customer
* 新建账户的账户名,以及查询账户等操作
* @author DawnLee
* @version
* @data 2020-8-9 14:27:17
*
*/
public class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String f,String l) {
firstName = f;
lastName = l;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}按照如下的UML类图,创建相应的类,提供必要的结构。
Bank -customers:Customer[]
-numberOfCustomer:int+Bank() +addCustomer(f:string,l:String)
+getNumOfCustomer():int
+getCustomer(index:int):Customer- addCustomer()方法必须依照参数(姓,名)构造一个新的Customer对象,然后把它放到customer数组中。还必须吧numberOfCustomer属性的值加1.
- getNumOfCustomer()方法返回numberOfCustomer属性值。
- getCustomer()方法返回与给出的index参数相关的客户。
package experiment2;
/**
*
* @Description this关键字课后练习:实验二类3--Bank
* 新建用户并计数,将账户信息存入数组
* @author DawnLee
* @version
* @data 2020-8-9 14:31:13
*
*/
public class Bank {
private Customer[] customers = new Customer[10];
private int numberOfCustomer;
public Bank() {
//空参构造器
}
public void addCustomer(String f,String l) {
Customer customer = new Customer(f,l);
customers[numberOfCustomer++] = customer;
}
public int getNumOfCustomer() {
return numberOfCustomer;
}
public Customer getCustomer(int index) {
// return customers[index];//可能报异常
if(index >= 0 && index < numberOfCustomer) {
return customers[index];
}
return null;
}
}创建BankTest类,进行测试。
package experiment2;
/**
*
* @Description this关键字课后练习:实验二类4--测试类
* 测试各功能的使用
* @author DawnLee
* @version
* @data 2020-8-9 16:07:49
*
*/
public class BankTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("Dawn", "Lee");
bank.getCustomer(0).setAccount(new Account(2000));
bank.getCustomer(0).getAccount().withdraw(500);
System.out.println("账户名:" + bank.getCustomer(0).getFirstName() +bank.getCustomer(0).getLastName());
bank.addCustomer("Triabin", "Lee");
System.out.println("\n当前银行客户数量为:" + bank.getNumOfCustomer());
}
}- 运行
关键字:package、import
package
package关键字的使用
- 为了更好的实现项目中类的管理,提供包的概念。
- 使用package来声明类或接口所属的包,声明在源文件首行。
- 包,属于标识符,遵循标识符的命名规则、规范(全小写)、见名知意。
- 每“.”一次,就代表一层文件目录。
补充:同一个包下,不能命名同名的接口、类。
JDK中主要的包介绍
- java.lang—-包含一些Java语言的核心类,如String、Math、Integer、 System和
Thread,提供常用功能。 - java.net—-包含执行与网络相关的操作的类和接口。
- java.io—-包含能提供多种输入/输出功能的类。
- java.util—-包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
- java.text—-包含了Java进行JDBC数据库编程的相关类/接口。
- java.sql—-包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
MVC设计模式
MVC是常用的设计模式之一,将整个程序分为三个层次:视图模型层,控制器层,与
数据模型层。这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式
使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程
序的耦合性。
- 模型层:model,主要处理数据。
- 数据对象封装 model.bean/domain
- 数据库操作类 model.dao
- 数据库 model.db
- 控制层:controller,处理业务逻辑。
- 应用界面相关 controller.activity
- 存放fragment controller.fragment
- 显示列表的适配器 controller.adapter
- 服务相关的 controller.service
- 抽取的基类 controller.base
- 视图层:view,显示数据。
- 相关工具类 view.utils
- 自定义view view.ui
- 包(package)能使整个结构变得清晰
import
import关键字的使用
在源文件显式的使用import结构导入指定包下的类、接口。
声明在包的声明和类的声明之间。
如果需要导入多个包,则并列写出即可。
可以使用“xxx.*”的方式导入xxx包下所有结构。
如果使用的类或接口是java.lang包下定义的,则可以省略import结构。
如果使用的类或接口是本包下定义的,则可以省略import结构。
如果再源文件中使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
如果使用“xxx.*”的方式表明可以调用xxx包下所有结构。但如果使用的是xxx子包下的结构,仍需要显示导入。
import static:导入指定类或接口中的静态结构。
静态结构:属性或方法
章节练习题及面试题
类的实例化
代码实现
编写一个Student类,包含name、gender、age、id、score属性,分别为String、String、int、int、double类型。
类中声明一个say方法,返回String类型,方法返回信息中包含所有属性值。
package top.triabin._01; |
在另一个StudentTest类中的main方法中,创建Student对象,并访问say方法和所有属性,并将调用结果打印输出。
package top.triabin._01; |
- 运行结果
编程题1
定义一个丈夫Husband类,有姓名、年龄、妻子属性;
定义一个妻子Wife类,有姓名、年龄、丈夫属性。
丈夫类中有一个getInfo()方法,其中能显示自己的姓名、年龄和他妻子的姓名、年龄;
package top.triabin._02; |
妻子类中有一个getInfo()方法,能显示自己的姓名、年龄和她丈夫的姓名、年龄。
package top.triabin._02; |
定义一个测试类,创建妻子和丈夫对象,然后测试。
package top.triabin._02; |
- 运行结果
编程题2
定义银行账户类Account,有属性:卡号cid,余额balance,所属用户Customer,银行账户类Account有方法:
- getInfo(),返回String类型,返回卡的详细信息;
- 取钱方法withdraw(),参数自行设计,如果取钱成功,返回true,失败返回false;
- 存钱方法save(),参数自行设计,如果存钱成功,返回true,失败返回false。
package top.triabin._03; |
其中,Customer类有姓名、身份证号、联系电话、家庭住址等属性。Customer类有方法say(),返回String类型,返回他的个人信息。
package top.triabin._03; |
在测试类Bank中创建银行账户类对象和用户类对象,并设置信息与显示信息。
package top.triabin._03; |
- 运行结果
方法的使用
哪个选项和show()方法重载?
class Demo{ |
A.void show(int a,float c,int b){}//yes
B,void show(int a,int b,float c){}//一模一样。不可以出现在同一个类中。
C.int show(int a,float c,int b){return a;}//yes。
D.int show(int a,float c){return a;}//yes
方法的声明与调用
声明一个圆柱体类;
声明属性:底边的半径,和高;
声明方法:
方法的功能:在方法中打印圆柱体的详细信息
圆柱体的底边的半径是xxx,高是xxx,底面积是xxx,体积是xxx。
方法的功能:返回底面积
方法的功能:返回体积
方法的功能:为圆柱体的底边的半径,和高赋值
方法的功能:为圆柱体的底边的半径,和高赋值,并返回赋值的结果,如果底边的半径或高为<=0,赋值失败,返回false,否则返回true
package top.triabin._04;
public class Cylinder {
private double radius;
private double height;
public Cylinder() {
super();
}
public Cylinder(double radius, double height) {
super();
this.radius = radius;
this.height = height;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
/**
* 方法功能:返回底面积
*/
public double getBasalArea() {
return this.radius * this.radius * Math.PI;
}
/**
* 方法的功能:返回体积
*/
public double getVolume() {
return getBasalArea() * this.height;
}
/**
* 方法的功能:为圆柱体的底边的半径,和高赋值
*/
public void setRadiusHeight(double radius,double height) {
this.radius = radius;
this.height = height;
}
/**
* 方法的功能:为圆柱体的底边的半径,和高赋值,并返回赋值的结果,如果底边的半径或高为<=0,
* 赋值失败,返回false,否则返回true
*/
public boolean setRH(double radius,double height) {
if(radius <= 0 || height <= 0) {
return false;
}else {
this.radius = radius;
this.height = height;
System.out.println("radius = " + this.radius + "\nheight = " + this.height);
return true;
}
}
/**
* 方法的功能:在方法中打印圆柱体的详细信息
* 圆柱体的底边的半径是xxx,高是xxx,底面积是xxx,体积是xxx。
*
*/
public void pointInfo() {
System.out.println("圆柱的底边半径是" + this.radius + ",高是" + this.height + ",底面积是" + getBasalArea() + ",体积是" + getVolume() + "。");
}
}测试
package top.triabin._04;
public class Test {
public static void main(String[] args) {
Cylinder cylinder = new Cylinder(10,5);
System.out.println("测试1:");
cylinder.pointInfo();
System.out.println();
System.out.println("测试2:");
cylinder.setRadiusHeight(100, 10);
cylinder.pointInfo();
System.out.println();
System.out.println("测试3:");
boolean isDone = cylinder.setRH(50, 10);
System.out.println(isDone);
System.out.println("失败测试:");
isDone = cylinder.setRH(-100, 0);
System.out.println(isDone);
}
}
- 运行结果
方法的重载
方法重载(overload)必须满足____
A. 在不同class中定义的方法 B.在同一类型中定义的方法
C. 方法名必须相同 D.返回类型必须相同
E. 参数一定不同 F.参数可以相同
答案:BCE
写出输出结果
class Demo{ |
输出结果:
i=15
i=14
写出输出结果
class Demo{ |
输出结果:
abdcbdcb
以下代码的运行结果是什么?
public class Test1 { |
答案:ABDCBDCB
面向对象
面向对象的三大特征说明
答:面向对象有三大特点:封装、继承、多态。(如果要回答四个,可加上抽象性这一特点)
继承性
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
封装性
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
多态性
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
抽象性
抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
作用域public、private、protected及默认不写时的区别?
- public:修饰的结构在同一个工程(Project)中的结构都可调用;
- protected:同一个工程中不同包的子类、同一个包以内都可调用;
- 不写(缺省):同一个包中的结构都可调用;
- private:只在其所在类内部可以调用。
找错
public class Something { |
答案:错。局部变量前不能放置任何访问修饰符 (private,public,和protected)。
Java的内存管理之垃圾回收(了解)
分配:由JVM自动为其分配相应的内存空间
释放:由JVM提供垃圾回收机制自动的释放内存空间
垃圾回收机制(GC:Garbage Collection):将垃圾对象所占用的堆内存进行回收。Java的垃圾回收机制是JVM提供的能力,由单独的系统级垃圾回收线程在空闲时间以不定时的方式动态回收。
**垃圾对象**:不再被任何引用指向的对象。
面试题:
问:在程序中是否可以通知垃圾回收机制过来回收垃圾?
能,通过调用System.gc();或Runtime.getRuntime().gc();
再问:调用了System.gc();或Runtime.getRuntime().gc();后是立刻执行垃圾回收吗?
不是,该调用并不会立刻启动垃圾回收机制开始回收,但会加快垃圾回收机制的运行。
public class TestGC{ |
构造器
构造器Constructor是否可以被Override?
答:构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。
编程创建一个Box类,在其中定义三个变量表示立方体的长、宽和高,定义一个方法求立方体的体积。创建一个对象,求给定尺寸的立方体的体积。
(提供无参的构造器和一个有参的构造器)
package top.triabin._05; |
- 运行结果
定义一个圆类型
- 提供显示圆周长功能的方法
- 提供显示圆面积的方法
- 提供无参的构造器和一个有参的构造器
package top.triabin._06; |
设计一个Dog类,有名字、颜色和年龄属性,定义构造器初始化这些属性,定义输出方法show()显示其信息。
(提供无参的构造器和一个有参的构造器)
package top.triabin._07; |
- 运行结果
定义一个类,用于描述坐标点
o——————>X
|
|
|
Y P(X,Y)
- 具有计算当前点到原点距离的功能
- 求到任意一点(m,n)的距离
- 求到任意一点(Point p)的距离
- 具有坐标点显示功能,显示格式(x,y)
- 提供无参的构造器和一个有参的构造器
package top.triabin._08; |
- 运行结果
写一个人的类
属性:名字,性别,年龄;提供无参的构造器和一个有参的构造器
方法:①自我介绍的方法 ②吃饭的方法
创建一个对象“张三”
package top.triabin._09; |
- 运行结果
写一个汽车类
属性:品牌、车长、颜色、价格;
package top.triabin._10; |
创建五个对象:“捷达”,“宝马”,“劳斯莱斯”,“科鲁兹”,“迈锐宝”
提供无参的构造器和一个有参的构造器
package top.triabin._10; |
写一个课程类
属性:课程名;学时;任课老师;
package top.triabin._11; |
创建五个对象:“c语言”,“java编程”,“php网络编程”,“c++”,“数据结构”
提供无参的构造器和一个有参的构造器
package top.triabin._11; |
以下程序的运行结果是:
public class Test1 { |
答案:
B
A
AB
关于参数传递
练习一:写出结果
public class Test{ |
答案:4。和leftShift()方法没关系。
练习二:写出结果
public class Demo{ |
答案:1。
练习三
public class TestA { |
练习四:写出结果
class Value{ |
A.15 0 20
B.15 0 15
C.20 0 20
D.0 15 20
A is correct.
练习五
public class Test { |
What is the output from line 5 of the Test class?
A.5 B.10 C.12
D.17 E.14
练习六
import java.util.Arrays; |
答案:
/* |
以下代码的执行结果是什么?
public static void main(String[] args) { |
答案:i=0
以下程序的运行结果:
public static void main(String[] args) { |
答案:
world
abcde
以下代码的运行结果是?
public class Test { |
答案:101
简答
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的
补足compare函数内的代码,不许添加其他函数。
class Circle { |
Eclipse快捷键的使用
- Eclipse中快捷键的使用:
- 补全代码的声明:Alt + /
- 快速修复:Ctrl + 1
- 批量导包:Ctrl + Shift + O
- 单行注释:Ctrl + /
- 多行注释:Ctrl + Shift + /
- 取消多行注释:Ctrl + Shift + \
- 复制指定行的代码:Ctrl + Alt + Down/Up
- 删除指定行的代码:Ctrl + D
- 上下移动代码:Alt + Up/Down
- 向下插入空行:Shift + Enter
- 向上插入空行:Ctrl + Shift + Enter
- 如何查看源代码:Ctrl + 点击指定的结构 或 Ctrl + Shift + T
- 退回到前一个编辑的页面:Alt + Left
- 进入到下一个编辑的页面(针对于上面那条来说的):Alt + Right
- 光标选中指定的类,查看继承树结构:Ctrl + T
- 格式化代码:Ctrl + Shift + F
- 选中行数整体后移:Tab
- 选中行数整体前移:Shift + Tab
- 在当前类中,显示类结构,并支持搜索指定的方法、属性等:Ctrl + O
- 批量修改指定的变量名、方法名、类名等:Alt + Shift + R
- 选中结构大小写切换–变成大写:Ctrl + Shift + X
- 选中结构大小写切换–变成小写:Ctrl + Shift + Y
- 调出生成getter/setter/构造器等结构:Alt + Shift + S
- 显示当前选择资源(工程or文件)的属性:Alt + Enter
- 快速查找–参照选中的word快速定位到下一个:Ctrl + K
- 关闭当前窗口:Ctrl + W
- 关闭所有窗口:Ctrl + Shift + W
- 查看指定结构使用过的地方:Ctrl + Alt + G
- 查找与替换:Ctrl + F
- 最大化当前的View:Ctrl + M
- 直接定位到当前的首位:Home
- 直接定到当前的末位:End