知识点1:可变形参的方法(jdk5.0新特性)
package com.atguigu.java;
/**
*
*
* 测试java中方法的可变形参的使用(jdk5.0的新特性)
*
* 1. 可变形参的格式:数据类型 ... 参数名
* 2. 在调用可变形参的方式时,可以给可变形参赋值的参数个数为:0个,1个,2个,....
* 3. 可变形参的方法与同一个类中,相同方法名的多个方法间构成重载。(除了第4点中的情况)
* 4. 可变形参的方法a与 参数同类型的数组的形参的方法b 不能在一个类中同时声明。
* 5. 可变形参要求必须声明在方法的形参的最后。
* 6. 一个方法的形参位置最多只能声明一个可变形参。
*
*/
public class ArgsTest {
public static void main(String[] args) {
ArgsTest test = new ArgsTest();
test.sum(3);
test.sum(3,4);
test.sum();
// test.sum(new int[]{1,2,3,4,5});
test.sum(1,2,3,4,5);
}
public void sum(int i,int j){
System.out.println( i + j);
}
public void sum(int i){
System.out.println(i * i);
}
public void sum(int ... arr){
System.out.println("可变形参的方法");
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
//与上一个方法不能同时存在
// public void sum(int[] arr){
// for(int i = 0;i < arr.length;i++){
// System.out.println(arr[i]);
// }
// }
public void sum(String s,int ... arr){
}
}
知识点2:方法的参数传递机制:值传递(重点、难点)
1. 方法内变量的传递
package com.atguigu.java;
/**
*
* 变量间的传递规则:
*
* 基本数据类型:将基本数据类型变量保存的数据值传递过去。
*
* 引用数据类型:将引用数据类型变量保存的对象(或数组)地址值传递过去。
*
*/
public class VariableTansferTest {
public static void main(String[] args) {
int m = 10;
//主要看这:
int n = m;
System.out.println("m = " + m);
System.out.println("n = " + n);
m = 20;
System.out.println("m = " + m);
System.out.println("n = " + n);
System.out.println("#######################");
Order o1 = new Order();
o1.orderId = 1001;
System.out.println(o1.orderId);//1001
//主要看这:
Order o2 = o1;
System.out.println(o1);
System.out.println(o2);
o2.orderId = 1002;
System.out.println(o1.orderId);//1002
}
}
class Order{
int orderId;
}
2. 方法参数的传递机制
/**
*
* 1. 形参:方法声明时,小括号内声明的参数
* 实参:方法调用时,实际传递过去的参数
*
*
* 2. 方法的参数传递机制:值传递机制
* 对于基本数据类型来讲,传递的是基本数据类型变量保存的数据值。
* 对于引用数据类型来讲,传递的是引用数据类型变量保存的地址值。
*
*/
- 代码举例1
public class ValueTransferTest1 {
public static void main(String[] args) {
int m = 10;
int n = 20;
System.out.println("m = " + m);
System.out.println("n = " + n);
//交换两个变量的值
// int temp = m;
// m = n;
// n = temp;
//调用方法,实现变量的交换:No
ValueTransferTest1 test = new ValueTransferTest1();
test.swap(m,n);
System.out.println("m = " + m);
System.out.println("n = " + n);
}
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
}
对应的图示:
- 代码举例2
public class ValueTransferTest2 {
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);
ValueTransferTest2 test = new ValueTransferTest2();
//交换两个变量的值:yes!
test.swap(data);
//思考:是否可以交换m和n:NO!
// test.swap(data.m,data.n);
System.out.println("m = " + data.m + ", n = " + data.n);
}
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
public void swap(Data data){
int temp = data.m;
data.m = data.n;
data.n = temp;
}
}
class Data{
int m;
int n;
}
对应的图示:
- 练习1:
对应的内存结构:
- 练习2:见《补充:对象数组》
知识点3:递归方法
/**
*
* 递归方法:一个方法体内调用它自身。
* 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
* 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
*/
public class RecurionTest {
public static void main(String[] args) {
RecurionTest test = new RecurionTest();
System.out.println(test.getSum(100));
System.out.println(test.getSum1(100));
System.out.println(test.f(10));
}
//计算1-100自然数的和,并返回
public int getSum(int num){
int sum = 0;
for(int i = 1;i <= num;i++){
sum += i;
}
return sum;
}
//递归举例1:计算1-100自然数的和,并返回
public int getSum1(int num){
if(num == 1){
return 1;
}else{
return num + getSum1(num - 1);
}
}
//递归举例2:n!
public int multiply(int num){
if(num == 1){
return 1;
}else{
return num * multiply(num - 1);
}
}
//递归举例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
//其中n是大于0的整数,求f(10)的值。
public int f(int n){
if(n == 0){
return 1;
}else if(n == 1){
return 4;
}else{
return 2*f(n - 1) + f(n - 2);
}
}
//递归举例4:已知一个数列:f(20) = 1,f(21) = 4,f(n+2) = 2*f(n+1)+f(n),
//其中n是大于0的整数,求f(10)的值。
public int func(int n){
if(n == 20){
return 1;
}else if(n == 21){
return 4;
}else{
return func(n + 2) - 2 * func(n + 1);
}
}
//递归举例5:斐波那契数列(Fibonacci)
// 1 1 2 3 5 8 13 21 34 55
// 规律:一个数等于前两个数之和: f(n) = f(n - 1) + f(n - 2)
//递归举例6:汉诺塔
//递归举例7:遍历指定文件目录下的所有文件名
public void printFileName(File dir){
if(dir.isFile()){//是文件
System.out.println(dir.getAbsolutePath());
}else{//是文件目录
File[] files = dir.listFiles();
for(int i = 0;i < files.length;i++){
printFileName(files[i]);
}
}
}
//拓展:计算指定文件目录的大小、删除指定的文件目录
//递归举例8:快速排序
}
知识点4:面向对象的特征一:封装性
1. 封装性的引入
/* 一、封装性的引入
* 1.背景
* 我们在创建了类的对象以后,可以通过"对象.属性"的方式给对象的属性赋值。此时,对象的属性的赋值需要满足相应
* 的数据类型和取值范围。在此之外,实际问题中可能还有其他的一些限制条件。(比如:legs要求是正数、偶数、0~30)
* 那么该如何添加限制条件呢?
* 2. 给属性提供公共(public)的setXxx()方法用于设置属性的值。在方法内,可以添加额外的限制条件。
* 给属性提供公共(public)的getXxx()方法用于获取属性的值。在方法内,可以添加额外的限制条件。
* 同时,将类中的属性xxx,设置为私有的(private)
*/
public class AnimalTest {
public static void main(String[] args) {
Animal a1 = new Animal();
a1.name = "大黄";
// a1.age = 5;
a1.setAge(5);
// a1.legs = -4;
a1.setLegs(4);
// System.out.println(a1.legs);
System.out.println(a1.getLegs() + "!!!");
a1.info();
a1.eat();
// a1.sleep();
}
}
class Animal{//动物类
//属性
String name;
private int age;
private int legs;//腿的个数
//方法
//给legs属性赋值的方法
public void setLegs(int l){
if(l >= 0 && l % 2 == 0 && l <= 30){
legs = l;
}else{
System.out.println("输入的数据不合法!");
}
}
//获取legs属性值的方法
public int getLegs(){
return legs;
}
//提供关于age属性的set和get方法
public void setAge(int a){
age = a;
}
public int getAge(){
return age;
}
public void eat(){
System.out.println("动物进食");
sleep();
}
private void sleep(){
System.out.println("动物休息");
}
public void info(){
System.out.println("name = " +name + ", age = " + age + ", legs = " +legs);
}
}
2. 封装性的体现
/*二、封装性的体现:体现为4种不同的权限:(从小到大)private < 缺省 < protected < public
* 体现之一:私有化类的属性,提供公共的get和set方法,用于获取和设置此属性的值。
* 体现之二:私有化类的方法,表示此方法仅在类内部使用。不会暴露给类外使用
* 体现之三:单例模式(涉及到私有化构造器)(后面讲)
*
* 通过使用4种不同的权限修饰类及类的内部结构,从而体现被修饰的结构在调用时的可见性的大小!
*
* 三、4种不同的权限修饰符:private < 缺省 < protected < public
* > 4种不同的权限修饰符可以用来修饰类的内部结构:属性、方法、构造器、内部类。
* > 修饰类的话,仅能使用2种权限:缺省 、 public
*/
- 便于理解
知识点5:类的成员之三:构造器
- 理解
/**
*
* 测试类的成员之三:构造器(或构造方法、Constructor)
* Constructor:construct:构建、构造、建造、建设
*
* 1. 构造器的作用:①创建类的对象 ② 给对象的属性初始化赋值
*
*
* 2. 说明:
* ① 如果没有显式声明类的构造器的话,则系统会默认提供一个空参的构造器。
* ② 构造器声明的格式:权限修饰符 类名(形参列表){}
* ③ 类中可以声明多个构造器,彼此之间构成重载。
* ④ 如果用户一旦显式声明了类的构造器,则系统不再提供参的构造器。
* ⑤ 类中一定会声明构造器。(自始至终都是对的)
*/
- 代码举例
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person("Tom",12);
p2.info();
}
}
class Person{
//属性
String name;
int age;
//构造器
public Person(){
System.out.println("Person()....");
}
public Person(String n){
name = n;
}
public Person(int a){
age = a;
}
public Person(String n,int a){
name = n;
age = a;
}
//方法
public void info(){
System.out.println("name = " + name + ", age = " + age);
}
public void eat(){
System.out.println("人吃饭");
}
}
补充:对象数组
- Student类
class Student {//学生类
int number;//学号
int state;//年级
int score;//成绩
public void info() {
System.out.println("number : " + number +
", state : " + state + ", score : " + score);
}
}
- StudentUtil类
package com.atguigu.exer;
/**
*
* 将上课练习4:Student对象数组问题中涉及到的相关操作,封装进方法,测试执行。
*
* 比如:打印年级是3年级的方法;学生数组对象的排序;遍历Student数组中对象的方法
*/
public class StudentArrayTest { //测试类
public static void main(String[] args) {
StudentArrayUtil util = new StudentArrayUtil();
//创建学生数组
Student[] stus = util.getStudentArray(20, 1, 6, 0, 100);
//打印学生的基本信息
util.printStudentArrayInfo(stus);
//问题一:打印出3年级(state值为3)的学生信息。
util.getStudentsInState(stus,3);
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
util.printStudentArray(stus,"descend");
System.out.println("排序后:");
//遍历
util.printStudentArrayInfo(stus);
}
}
class Student {//学生类
int number;//学号
int state;//年级
int score;//成绩
public void info() {
System.out.println("number : " + number +
", state : " + state + ", score : " + score);
}
}
/**
* 操作Student数组的工具类
*/
class StudentArrayUtil{
/**
* 遍历学生数组元素的信息
* @param stus
*/
public void printStudentArrayInfo(Student[] stus){
//打印学生的基本信息
for (int i = 0; i < stus.length; i++) {
Student s = stus[i];
s.info();
}
}
/**
* 打印出指定年级的学生信息。
* @param stus 学生数组
* @param state 指定年级
*/
public void getStudentsInState(Student[] stus,int state){
for(int i = 0;i < stus.length;i++){
if(stus[i].state == state){
stus[i].info();
}
}
}
// public void printStudentArray(Student[] stus){
// printStudentArray(stus,"ascend");
// }
/**
* 使用冒泡排序按学生成绩排序,并遍历所有学生信息
* @param stus
*/
public void printStudentArray(Student[] stus,String sort){
if("ascend".equals(sort)){//升序
for (int i = 0; i < stus.length - 1; i++) {
for (int j = 0; j < stus.length - 1 - i; j++) {
if (stus[j].score > stus[j + 1].score) {
swap(stus,j,j + 1);
// swap(stus[j],stus[j + 1]);
}
}
}
}else if("descend".equals(sort)){//降序
for (int i = 0; i < stus.length - 1; i++) {
for (int j = 0; j < stus.length - 1 - i; j++) {
if (stus[j].score < stus[j + 1].score) {
swap(stus,j,j + 1);
// swap(stus[j],stus[j + 1]);
}
}
}
}else{
System.out.println("输入的排序方式有误!");
}
}
/**
* 交换stus数组中指定的index1和index2位置上的元素
* @param stus
* @param index1
* @param index2
*/
private void swap(Student[] stus,int index1,int index2){
Student tempStudent = stus[index1];
stus[index1] = stus[index2];
stus[index2] = tempStudent;
}
//错误的写法
public void swap(Student s1,Student s2){
Student tempStudent = s1;
s1 = s2;
s2 = tempStudent;
}
/**
* 返回学生数组
* @param length
* @param minState
* @param maxState
* @param minScore
* @param maxScore
* @return
*/
public Student[] getStudentArray(int length,int minState,int maxState,int minScore,int maxScore){
//1. 创建Student[]的数组,长度为length ---> 动态初始化
Student[] stus = new Student[length];
//2.通过循环,给每个数组元素赋值(即:创建对象)
for (int i = 0; i < stus.length; i++) {
stus[i] = new Student();
//3. 给数组中的每个Student对象的属性赋值
stus[i].number = i + 1;
stus[i].state = (int) (Math.random() * (maxState - minState + 1) + minState); //[minState,maxState]
stus[i].score = (int) (Math.random() * (maxScore - minScore + 1) + minScore);//[minScore,maxScore]
}
return stus;
}
}
- StudentTest测试类
/**
*
* 将上课练习4:Student对象数组问题中涉及到的相关操作,封装进方法,测试执行。
*
* 比如:打印年级是3年级的方法;学生数组对象的排序;遍历Student数组中对象的方法
*/
public class StudentArrayTest { //测试类
public static void main(String[] args) {
StudentArrayUtil util = new StudentArrayUtil();
//创建学生数组
Student[] stus = util.getStudentArray(20, 1, 6, 0, 100);
//打印学生的基本信息
util.printStudentArrayInfo(stus);
//问题一:打印出3年级(state值为3)的学生信息。
util.getStudentsInState(stus,3);
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
util.printStudentArray(stus,"descend");
System.out.println("排序后:");
//遍历
util.printStudentArrayInfo(stus);
}
}