面向对象编程---上

目录

学习面向对象内容的三条主线

一、面向过程与面向对象  

二、Java基本元素:类和对象

三、对象的创建(new)和使用(.)

四、类的成员之一:属性

五、类的成员之二:方法

理解“万事万物皆对象”

内存解析的说明

​  匿名对象的使用

六、再谈方法

七、OOP特征一:封装与隐藏

面向对象的特征一:封装与隐藏     3W:what? why? how?

一、问题的引入:

  二、封装性的体现:

  三、封装性的体现,需要权限修饰符来配合

八、类的成员之三:构造器

一、构造器的作用:

 二、说明:

总结:属性赋值的先后顺序

拓展知识:JavaBean

拓展知识:UML类图

九、关键字:this

十、关键字:package、import

  一、package关键字的使用

二、import关键字的使用


学习面向对象内容的三条主线

1.Java类及类的成员:属性、方法、构造器;代码块、内部类

2.面向对象的三大特征:封装性、继承性、多态性、(抽象性) 

3.其他关键字:this、super、static、final、abstract、interface、package、import等

原则:“大处着眼,小处着手”

一、面向过程与面向对象  

例子:“人把大象装进冰箱”
 
  1. 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
  ① 把冰箱门打开
  ② 抬起大象,塞进冰箱
  ③ 把冰箱门关闭
  2. 面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
  人{
          打开(冰箱){
              冰箱.开开();
          }
          抬起(大象){
              大象.进入(冰箱);
          }
          关闭(冰箱){
              冰箱.闭合();
          }
  }  
  冰箱{
          开开(){}
          闭合(){}
 }
  大象{
          进入(冰箱){
          }
 }  

二、Java基本元素:类和对象

类:对一类事物的描述,是抽象的、概念上的定义

对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)

        >可以理解为:类 = 抽象概念的人; 对象 = 实实在在的某个人

        >面向对象程序设计的重点是类的设计

        >设计类,就是设计类的成员

                属性 = 成员变量 = field = 域、字段

                方法 = 成员方法 = 函数 = method

类和对象的使用(面向对象思想落地的实现):
   1.创建类,设计类的成员
   2.创建类的对象
   3.通过“对象.属性”或“对象.方法”调用对象的结构

三、对象的创建(new)和使用(.)

创建类的对象 = 类的实例化 = 实例化类

调用对象的结构:属性、方法
        调用属性:“对象.属性”

        调用方法:“对象.方法”

如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。

对象的内存解析:

编译完源程序以后,成成一个或多个字节码文件。

我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。(内存解析是在运行时进行的!)

堆(heap):存放对象的实例,例如所有new出来的东西、数组

栈(stack):我们在java中常说的栈通常是指虚拟机栈,用于存放局部变量

方法区:存放加载的类信息、常量、静态变量

一个关于Person类的测试代码 

public class PersonTest {
	public static void main(String[] args) {
		//创建Person类的对象
		Person p1 = new Person();
		Person p2 = new Person();
		//类似Scanner scanner = new Scanner(System.in);
		p1.name = "Tom";
		p1.isMale = true;
		System.out.println(p1.name);
		
		p1.eat();
		p1.sleep();
		p1.talk("Chinese");
		
		System.out.println(p2.name);
		System.out.println(p2.isMale);
		
		Person p3 = p1;
		System.out.println(p3.name);
		p3.age = 10;
		System.out.println(p1.age);
	}
}

class Person{
	
	//属性
	String name;
	int age = 1;
	boolean isMale;
	
	//方法
	public void eat() {
		System.out.println("人可以吃饭");
	}
	
	public void sleep() {
		System.out.println("人可以睡觉");
	}
	
	public void talk(String language) {
		System.out.println("人可以说话,说的是:" + language);
	}
	
	
}

四、类的成员之一:属性

 * 类中属性的使用
 * 
 * 属性(成员变量)   vs  局部变量
 * 1.相同点:
 *         1.1  定义变量的格式:数据类型  变量名 = 变量值
 *         1.2 先声明,后使用
 *         1.3 变量都有其对应的作用域 
 * 
 * 2.不同点:
 *         2.1 在类中声明的位置的不同
 *         属性:直接定义在类的一对{}内
 *         局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
 *         
 *         2.2 关于权限修饰符的不同
 *         属性:可以在声明属性时,指明其权限,使用权限修饰符。
 *             常用的权限修饰符:private、public、缺省、protected  --->封装性
 *             目前,大家声明属性时,都使用缺省就可以了。
 *         局部变量:不可以使用权限修饰符。
 *   
 *         2.3 默认初始化值的情况:
 *         属性:类的属性,根据其类型,都有默认初始化值
 *             整型(byte、short、int、long):0
 *             浮点型(float、double):0.0
 *             字符型(char):0  (或'\u0000')
 *             布尔型(boolean):false
 * 
 *             引用数据类型(类、数组、接口):null
 * 
 *         局部变量:没有默认初始化值。
 *         意味着,我们在调用局部变量之前,一定要显式赋值。
 *         特别地:形参在调用时,我们赋值即可。
 * 
 *         2.4 在内存中加载的位置:
 *         属性:加载到堆空间中(非static)
 *         局部变量:加载到栈空间

测试代码---UserTest

public class UserTest {
	public static void main(String[] args) {
		User u1 = new User();
		System.out.println(u1.name);	
		System.out.println(u1.name);	
		System.out.println(u1.name);	
		}

}

class User{
	String name;
	int age;
	boolean isMale;
	
	public void talk(String language) {
		System.out.println("我们使用" + language + "进行交流");
	}
	
	public void eat() {
		String food = "烙饼";
		System.out.println("北方人喜欢吃: " + food);
	}
}

五、类的成员之二:方法

 类中方法的声明和使用
  
  方法:描述类应该具有的功能。

 
   比如:

      Math类:sqrt()\random() \...
      Scanner类:nextXxx() ...
      Arrays类:sort() \ binarySearch() \ toString() \ equals() \ ...

快捷键:

Ctrl + Shift + t

Ctrl + o

  1.举例:
  public void eat(){}
  public void sleep(int hour){}
  public String getName(){}
  public String getNation(String nation){}
  2. 方法的声明:权限修饰符  返回值类型  方法名(形参列表){
                      方法体
                } 
    注意:static、final、abstract 来修饰的方法,后面再说。
    
  3. 说明:
          3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
              Java规定的4种权限修饰符:private、public、缺省、protected  -->封装性再细说
  
          3.2 返回值类型: 有返回值  vs 没有返回值
              3.2.1  如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,                         需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
                       如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法                         中就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思

                3.2.2 我们定义方法该不该有返回值?

                  ① 看题目要求        ② 凭经验:具体问题具体分析

           3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”        

           3.4 形参列表: 方法可以声明0个,1个,或多个形参。

                 3.4.1 格式:数据类型1 形参1,数据类型2 形参2,...

                 3.4.2 我们定义方法时,该不该定义形参?

                ① 题目要求        ② 凭经验:具体问题具体分析

          3.5 方法体:方法功能的体现。

4.return关键字的使用:
     1.使用范围:使用在方法体中
     2.作用:① 结束方法
                   ② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
     3.注意点:return关键字后面不可以声明执行语句。

5. 方法的使用中,可以调用当前类的属性或方法

      特殊的:方法A中又调用了方法A:递归方法。
      方法中,不可以定义方法!!!。

测试代码---CustomerTest

public class CustomerTest {
	public static void main(String[] args) {
		Customer cust1 = new Customer();
		
		cust1.eat();
		cust1.sleep(8);
	}
}

class Customer{
	
	String name;
	int age;
	boolean isMale;
	
	public void eat() {
		System.out.println("客户吃饭");
		return;//此处表示结束该方法
		//return后不可以声明表达式
		
//		System.out.println("hello");
	}
	
	public void sleep(int hour) {
		System.out.println("休息了" + hour +"个小时");
		eat();
//		sleep(10);
	}
	
	public String getname() {
		
		if (age > 18) {
			return name;
		}else {
			return "Tom";
		}
	}
	
	public String getNation(String nation) {
		String info = "我的国籍是:" + nation;
		return info;
	}
	
	public void info(){
		//不能在方法里再定义一个方法
//		public void swim() {
//			
//		}
	}
}

练习题

  1.1 创建一个Person类

public class Person {
	
	String name;
	int age;
	/**
	 * sex:0表明是女性
	 * sex:1表明是男性
	 * 
	 */
	int sex;
	
	public void study() {
		System.out.println("studying");
	}
	
	public void showAge() {
		System.out.println("age:" + age);
	}
	
	public int addAge(int i) {
		age += i;
		return age;
	}
}

 1.2 创建一个PersonTest类 

public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		
		p1.name = "Tom";
		p1.age = 18;
		p1.sex = 1;
		
		p1.study();
		
		p1.showAge();
		
		int newAge = p1.addAge(2);
		System.out.println(p1.name + "的新年龄为:" + newAge);
		
		System.out.println(p1.age);
		
		Person p2 = new Person();
		p2.showAge();
		p2.addAge(10);
		p2.showAge();
		p1.showAge();
		
		
	}
}

public class CircleTest {
	public static void main(String[] args) {
		
		Circle c1 = new Circle();
		
		c1.radius = 3.1;
		
		//对应方式一:
//		double area = c1.findArea();
//		System.out.println(area);
		
		c1.findarea();
	}
}


class Circle{
	double radius;
	
	//求圆的面积
	//方式一:
//	public double findArea() {
//		double area = Math.PI * radius * radius;
//		return area;
//	}
	
//	方式二:
	public void findarea() {
		double area = Math.PI * radius * radius;
		System.out.println("面积为:" + area);
	}
		
}

 

public class Exer3Test {
	public static void main(String[] args) {
		Exer3Test test = new Exer3Test();
		//3.1测试
//		test.method();
		
		//3.2测试
		//方式一:
//		int area = test.method();
//		System.out.println("面积为:" + area);
		
		//方式二:
//		System.out.println(test.method());
		
		//3.3测试
		int area = test.method(12, 10);
		System.out.println("面积为:" + area);
	}
	
	// 3.1
//	public void method() {
//		for (int i = 0; i < 10; i++) {
//			for (int j = 0; j < 8; j++) {
//				System.out.print("* ");
//			}
//			System.out.println();
//		}
//	}
	
	//3.2
//	public int method(){
//		for (int i = 0; i < 10; i++) {
//			for (int j = 0; j < 8; j++) {
//				System.out.print("* ");
//			}
//			System.out.println();
//		}
//		
//		return 10 * 8;
//	}
	
	//3.3
	public int method(int m, int n) {
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print("* ");
			}
			System.out.println();
		}
		return m * n;
	}
}

 

public class StudentTest {
	public static void main(String[] args) {
		
		//声明Student类型的数组
		Student[] stus = new Student[20];
		
		for (int i = 0; i < stus.length; i++) {
			//给数组元素赋值
			stus[i] = new Student();
			//给Student对象的属性赋值
			stus[i].number = i + 1;
			//假设年级:[1, 6]
			stus[i].state = (int)(Math.random() * (6 -1 + 1) + 1);
			//成绩:[0, 100]
			stus[i].score = (int)(Math.random() * (100 - 0 + 1) + 0);
		}
		
		//遍历学生数组
		for (int i = 0; i < stus.length; i++) {
//			System.out.println(stus[i].number + "," + stus[i].state + "," + stus[i].score);
			System.out.println(stus[i].info());
		}
		
		System.out.println("*************");
		
		//问题一:打印出3年级(state值为3)的学生信息。
		for (int i = 0; i < stus.length; i++) {
			if (stus[i].state == 3) {
				System.out.println(stus[i].info());
			}
		}
		
		System.out.println("###########");
		
		//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
		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) {
					Student temp = stus[j];
					stus[j] = stus[j + 1];
					stus[j + 1] = temp;
				}
			}
		}
		
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].info());
		}
		
	}

}



class Student{
	int number; //学号
	int state;
	int score;
	
	//显示学生信息的方法
	public String info() {
		return "学号:" + number + ",年级:" + state + ",成绩:" + score;
		
	}
}

代码改进:将操作数组的功能封装到方法中

public class StudentTest2 {
	public static void main(String[] args) {

		// 声明Student类型的数组
		Student2[] stus = new Student2[20];

		for (int i = 0; i < stus.length; i++) {
			// 给数组元素赋值
			stus[i] = new Student2();
			// 给Student对象的属性赋值
			stus[i].number = i + 1;
			// 假设年级:[1, 6]
			stus[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);
			// 成绩:[0, 100]
			stus[i].score = (int) (Math.random() * (100 - 0 + 1) + 0);
		}

		StudentTest2 test = new StudentTest2();
		// 遍历学生数组
		test.print(stus);
		System.out.println("*************");

		// 问题一:打印出3年级(state值为3)的学生信息。
		test.searchState(stus, 3);
		System.out.println("###########");

		// 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
		 test.sort(stus);
		 test.print(stus);
	}
	

	/**
	* @Title: print 
	* @Description: 遍历Student2[]数组的操作
	* @param  stus  要遍历的数组 
	* @return void    返回类型
	 */
	public void print(Student2[] stus) {
		for (int i = 0; i < stus.length; i++) {
//					System.out.println(stus[i].number + "," + stus[i].state + "," + stus[i].score);
			System.out.println(stus[i].info());
		}
	}
/**
* 
* @Title: searchState 
* @Description: 查找Student2[]数组中指定年级的信息
* @param  stus 要查找的数组
* @param  state  要找的年级 
* @return void    返回类型
*/
	public void searchState(Student2[] stus, int state) {
		for (int i = 0; i < stus.length; i++) {
			if (stus[i].state == state) {
				System.out.println(stus[i].info());
			}
		}
	}
	
	/**
	 * 
	* @Title: sort 
	* @Description: 给Student2[]数组排序
	* @param stus  要排序的数组 
	* @return void    返回类型
	 */
	public void sort(Student2[] stus) {
		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) {
					Student2 temp = stus[j];
					stus[j] = stus[j + 1];
					stus[j + 1] = temp;
				}
			}
		}
	}

}

class Student2 {
	int number; // 学号
	int state;
	int score;

	// 显示学生信息的方法
	public String info() {
		return "学号:" + number + ",年级:" + state + ",成绩:" + score;

	}
}

 补充:冒泡排序算法的实现

/*
 * 数组冒泡排序的实现
 * 
 */
public class BubbleSort {
	public static void main(String[] args) {
		
		int[] arr = new int[] {12,35,35,79,-56,-35,88,20,0,21};
		
		//冒泡排序
		 for(int i = 0; i < arr.length - 1; i++) {
			 
			 for (int j = 0; j < arr.length - 1 - i; j++) {
				if(arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp; 
				}
			}
		 }
		
		
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + "\t");
		}
	}
}

 复习题:

1. 面向对象思想编程内容的三条主线分别是什么?

① 类及类的成员:属性、方法、构造器;代码块、内部类

② 面向对象的三大特征:封装、继承、多态 

③ 其它关键字:this,super,abstract,interface,static,final,package,import

面向对象的编程思想?

(类、对象;面向对象的三大特征(封装、继承、多态);。。。)

2. 谈谈你对面向对象中类和对象的理解,并指出二者的关系

类:抽象的、概念上的内容

对象:实实在在存在的一个个体。

对象是由类派生出来(new出来)的。(对象是类的实例化)

3. 面向对象思想的体现一:类和对象的创建和执行操作有哪三步?

① 创建类

② 类的实例化

③ 调用对象的结构:”对象.属性” “对象.方法”

4. 画出如下代码在执行时的内存分配情况

class Car{

       String color = "red";

       int num = 4;

       void show(){

               int a = 10;

          System.out.println("color="+color+",num="+num);

        }

  }

class CarTest {

public static void main(String[] args) {

      Car c1 = new Car();  

      Car c2 = new Car();

          c1.color = "blue"; 

          c1.show();  

          c2.show();

}

5. 类的方法内是否可以定义变量?是否可以调用属性?是否可以定义方法?是否可以调用方法?

是;是;否;是

6. 完成一个项目(或功能)的思路:

7. 回归变量的分类:

        方式一:按照数据类型

        方式二:按照在类中声明的位置

  

理解“万事万物皆对象”

1.在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构

         >Scanner,String等
         >文件:File
         >网络资源:URL
 2.涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。

内存解析的说明

        1.引用类型的变量,只可能存储两类值:null  或  地址值(含变量的类型)


  
匿名对象的使用

  1.理解:我们创建的对象,没有显式的赋给一个变量名。即为匿名对象
  2.特征:匿名对象只能调用一次
  3.使用:如下

public class Instance {
	public static void main(String[] args) {
		Phone p = new Phone();
//		p = null;
		System.out.println(p);
		
		p.sendEmail();
		p.playGames();
		
		//匿名对象
//		new Phone().sendEmail();
//		new Phone().playGames();
		
		new Phone().price = 1999;
		new Phone().showPrice();//0.0
		System.out.println("**********");
		
		PhoneMall mall = new PhoneMall();
		//匿名对象的使用,此时将地址值其实是赋给了形参phone
		//此时调用的是同一个对象
		mall.show(new Phone());
	}
}

class PhoneMall{
	
	public void show(Phone phone) {
		phone.sendEmail();
		phone.playGames();
	}
}


class Phone{
	double price;
	
	public void sendEmail() {
		System.out.println("发邮件");
	}
	
	public void playGames() {
		System.out.println("玩游戏");
	}
	
	public void showPrice() {
		System.out.println("手机价格为:" + price);
	}
}

 工具类的封装:

 1.1造工具类ArrayUtil

public class ArrayUtil {

	// 求数组的最大值
	public int getMax(int[] arr) {
		int maxValue = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if (maxValue < arr[i]) {
				maxValue = arr[i];
			}
		}
		return maxValue;
	}

	// 求数组的最小值
	public int getMin(int[] arr) {
		int minValue = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if (minValue > arr[i]) {
				minValue = arr[i];
			}
		}
		return minValue;
	}

	// 求数组的总和
	public int getSum(int[] arr) {
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
		}
		return sum;
	}

	// 求数组的平均值
	public int getAvg(int[] arr) {
		return getSum(arr) / arr.length;
	}

	// 翻转数组
	public void reverse(int[] arr) {
		for (int i = 0; i < arr.length / 2; i++) {
			int temp = arr[i];
			arr[i] = arr[arr.length - i - 1];
			arr[arr.length - i - 1] = temp;
		}
	}

	// 复制数组
	public int[] copy(int[] arr) {
		int[] arr1 = new int[arr.length];
		for (int i = 0; i < arr1.length; i++) {
			arr1[i] = arr[i];
		}
		return arr1;
	}

	// 数组排序
	public void sort(int[] arr) {
		// 冒泡排序
		for (int i = 0; i < arr.length - 1; i++) {

			for (int j = 0; j < arr.length - 1 - i; j++) {

				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}

			}

		}
	}

	// 遍历数组
	public void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + "\t");
		}
		System.out.println();
	}

	// 查找指定元素
	public int getIndex(int[] arr, int dest) {
		// 线性查找:

		for (int i = 0; i < arr.length; i++) {

			if (dest == arr[i]) {
				return i;
			}
		}
		
		return -1; //返回一个负数表示没有找到
		}
	}

1.2工具类的测试ArrayUtilTest

public class ArrayUtilTest {
	public static void main(String[] args) {
		
		ArrayUtil util = new ArrayUtil();
		int[] arr = new int[]{32,20,5,-8,0,99,5,-899};
		int max = util.getMax(arr);
		System.out.println("最大值为:" + max);
		
//		System.out.println("排序前:");
//		util.print(arr);
//		
//		util.sort(arr);
//		
//		System.out.println("排序后:");
//		util.print(arr);
//		
//		System.out.println("查找:");
		int index = util.getIndex(arr, -5);
		if (index >= 0) {
			System.out.println("找到了,索引地址为:" + index);
		}else {
			System.out.println("没找到");
		}
	}
}

六、再谈方法

方法的重载(overload)  loading...

  1.定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
     
 "两同一不同":同一个类、相同方法名
            参数列表不同:参数个数不同,参数类型不同
 
  2. 举例:
    Arrays类中重载的sort() / binarySearch()
 
  3.判断是否是重载:
    跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
    
  4. 在通过对象调用方法时,如何确定某一个指定的方法:
      方法名 ---> 参数列表

演示示例:

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");
	}
	
	//如下的3个方法不能与上述4个方法构成重载
//	public int getSum(int i,int j){
//		return 0;
//	}
	
//	public void getSum(int m,int n){
//		
//	}
	
//	private void getSum(int i,int j){
//		
//	}
	
	
}

练习:

1. 

2 + 3. 

public class OverloadExer {
	
	//1. 如下的三个方法构成重载
	public void mOL(int i){
		System.out.println(i * i);
		
	}
	public void mOL(int i,int j){
		System.out.println(i * j);
	}
	
	public void mOL(String s){
		System.out.println(s);
	}
	
	//2.如下的三个方法构成重载
	public int max(int i,int j){
		return (i > j)? i : j;
	}
	public double max(double d1,double d2){
		return (d1 > d2)? d1 : d2;
	}
	public double max(double d1,double d2,double d3){
		double max = (d1 > d2)? d1 : d2;
		return (max > d3)? max : d3;
	}
}

 可变个数形参的方法:
 1.jdk 5.0新增的内容
 2.具体使用:
   2.1 可变个数形参的格式:数据类型 ... 变量名
   2.2 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
   2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
   2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
   2.5 可变个数形参在方法的形参中,必须声明在末尾
   2.6  可变个数形参在方法的形参中,最多只能声明一个可变形参。

演示示例:

public class MethodArgsTest {
	
	public static void main(String[] args) {
		
		MethodArgsTest test = new MethodArgsTest();
		test.show(12);
//		test.show("hello");
//		test.show("hello","world");
//		test.show();
		
		test.show(new String[]{"AA","BB","CC"});
		
	}
	
	
	public void 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){
//		
//	}
	
	//The variable argument type String of the method 
	//show must be the last parameter
//	public void show(String ...strs,int i){
//		
//	}
	
}

 关于变量的赋值:
  如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
  如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。

演示示例:

public class ValueTransferTest {
	
	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;
	
}

方法的形参的传递机制:值传递
  1.形参:方法定义时,声明的小括号内的参数
    实参:方法调用时,实际传递给形参的数据
  2.值传递机制:
  如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
  如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值(含变量的数据类型)。例如:
                Person p1 = new Person();
                User u1 = p1; //编译错误

演示示例:

public class ValueTransferTest1 {
	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;
		
		ValueTransferTest1 test = new ValueTransferTest1();
		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;
	}
}
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);
		
		//交换m和n的值
//		int temp = data.m;
//		data.m = data.n;
//		data.n = temp;
		
		ValueTransferTest2 test = new ValueTransferTest2();
		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;
	
}

 练习题:

1.

 2.

3. 4.

public class ArrayPrintTest {
	public static void main(String[] args) {
		int[] arr = new int[]{1,2,3};
		System.out.println(arr);//地址值

		char[] arr1 = new char[]{'a','b','c'};
		System.out.println(arr1); //abc

	}
}

5.

/*
 * 定义一个Circle类,包含一个double型的radius属性代表圆的半径,
 * 一个findArea()方法返回圆的面积。
 * 
 */
public class Circle {
	double radius;//半径
	
	//求圆的面积
	public double findArea(){
		return Math.PI * radius * radius;
	}
}
/*
 * 考查参数的值传递
 * 
 * 定义一个类PassObject,在类中定义一个方法printAreas(),
 * 该方法的定义如下:public void printAreas(Circle c, int time)
 * 在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
 * 例如,time为5,则输出半径1,2,3,4,5,以及对应的圆面积。
 * 
 * 
 * 在main方法中调用printAreas()方法,调用完毕后输出当前半径值。程序运行结果如图所示。
 * 
 * 
 */
public class PassObject {
	
	public static void main(String[] args) {
		PassObject test = new PassObject();
		
		Circle c = new Circle();
		
		test.printAreas(c, 5);
		
		System.out.println("now radius is " + c.radius);
	}

	public void printAreas(Circle c, int time){
		
		System.out.println("Radius\t\tArea");
		int i = 1;
		for(;i <= time;i++){
			//设置圆的半径
			c.radius = i;
			double area = c.findArea();
			System.out.println(c.radius + "\t\t" + area);
		}
		
		//
//		c.radius = time + 1;
		c.radius = i;
		
	}
}

6.一个特殊的例子

public class ValueTransferTest {
	public static void main(String[] args) {
		
		String s1 = "hello";
		
		ValueTransferTest test = new ValueTransferTest();
		test.change(s1);
		
		System.out.println(s1);//hi~~
		
		
	}
	
	public void change(String s){
		s = "hi~~";
	}
}

递归方法的使用(了解)
 1.递归方法:一个方法体内调用它自身。
 2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
     递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。

练习题:

public class RecursionTest {

	public static void main(String[] args) {

		// 例1:计算1-100之间所有自然数的和
		// 方式一:
		int sum = 0;
		for (int i = 1; i <= 100; i++) {
			sum += i;
		}
		System.out.println(sum);
		// 方式二:
		RecursionTest test = new RecursionTest();
		int sum1 = test.getSum(100);
		System.out.println(sum1);

		System.out.println("*****************");
		int value = test.f(10);
		System.out.println(value);
		System.out.println("-----------------------");
		int fibonacci = test.Fibonacci(10);
		System.out.println(fibonacci);
		
//		System.out.println(test.hanoi(5,"A","B","C"));
		test.hanoi(3, "A", "B", "C");
		

	}

	// 例1:计算1-n之间所有自然数的和
	public int getSum(int n) {// 3

		if (n == 1) {
			return 1;
		} else {
			return n + getSum(n - 1);
		}

	}

	// 例2:计算1-n之间所有自然数的乘积:n!
	public int getSum1(int n) {

		if (n == 1) {
			return 1;
		} else {
			return n * getSum1(n - 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 f(n + 2) - 2 * f(n + 1);
			return 2 * f(n - 1) + f(n - 2);
		}
	}

	// 例4:斐波那契数列
//	方法一:递归
//	public int Fibonacci(int n) {
//		if (n == 0) {
//			return 0;
//		}
//		if(n == 1 || n == 2) {
//			return 1;
//		}
//		return Fibonacci(n - 1) + Fibonacci(n - 2);
//	}
//	方法二:循环
	public int Fibonacci(int n) {
		if (n == 0) {
			return 0;
		}
		if(n == 1 || n == 2) {
			return 1;
		}
		int[] a = new int[n + 1];
		a[1] = 1;
		a[2] = 1;
		for (int i = 3; i <= n; i++) {
			 a[i] = a[i - 1] + a[i - 2];
		}
		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + " ");
		}
		System.out.println();
		System.out.print("斐波那契数列的第" + n + "个数为:");
		return a[n];			
	}
	

	// 例5:汉诺塔问题
//	计算汉诺塔需要进行的次数:
//	public int hanoi(int n, String a, String b, String c) {
//		int x = 0;
//		if (n == 1) {
//			return 1;
//		} else {
//			return x + hanoi(n - 1, a, c, b) + hanoi(n - 1, b, a, c) + 1;
//		}
//	}
	public void hanoi(int n, String a,String b, String c) {
		if(n == 1) {
			System.out.println(a + "-->" + c);
		} else {
			hanoi(n - 1, a, c, b);
			System.out.println(a + "-->" + c);
			hanoi(n - 1, b, a, c);
		}
		
	}	
}

补充:快速排序

会先把数组中的一个数当做基准数,一般会把数组中最左边的数当做基准数然后从两边进行检索。先从右边检索比基准数小的。再从左边检索比基准数大的。如果检索到了,就停下,然后交换这两个元素。然后再继续检索。

i 和 j 一旦相遇,就停止检索把基准数和相遇位置的元素交换。

基准数和相遇位置的数交换完成,表示第一轮排序结束。
特点:基准数左边都比他小,右边都比他大。
以后先排基准数左边,排完之后再排基准数右边。方式和第一轮一样

public class quickSortTest {
	public static void main(String[] args) {
	
		
		int[] arr = new int[10000000];
		Random r = new Random();
		//给元素赋值
		for (int i = 0; i < arr.length; i++) {
			int num = r.nextInt();//如果不传递参数,随机数的范围是 int 范围
			arr[i] = num;
		}
		
		long start = System.currentTimeMillis();
		quickSort(arr, 0, arr.length - 1);
		long end = System.currentTimeMillis();
		System.out.println(end - start);
		
		/*
		//定义数组
		int[] arr = {20, 15, 6, 8, 99, 0, -35, 21};
		//调用方法,进行快速排序
		quickSort(arr, 0, arr.length - 1);
		
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]  + " ");
		}
		*/
	}
	
public static void quickSort(int[] arr, int left, int right) {
	//进行判断,如果左边索引比右边索引要大,是不合法的,直接使用return结束这个方法
	if (left > right) {
		return;
	}
	//定义变量保存基准数
	int base = arr[left];
	//定义变量i,指向最左边
	int i = left;
	//定义变量j,指向最右边
	int j = right;
	
	//当i 和 j不相遇的时候,在循环中进行检索。
	while(i != j) {
		//j从右往左检索比基准数小的,如果检索到比基准数小的就停下。
		//如果检索到比基准数达到或者相等的,就继续检索
		while(arr[j] >= base && i < j) {
			j--;//j从右往左移动
		}
		while(arr[i] <= base && i < j) {
			i++;//i从左往右移动
		}
	
		
		//代码走到这里,i停下了,j也停下。然后交换i和j位置的元素。
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
		//如果上面while循环的条件不成立,会跳出这个循环,往下执行
		//如果这个条件不成立,说明i和j相遇了
		//如果i和j相遇了,就交换基准数这个元素和相遇位置的元素
		//把相遇位置的元素赋值给基准数这个位置的元素
		arr[left] = arr[i];
		//把基准数赋值给相遇位置的元素
		arr[i] = base;
		
		//基准数在这里就归位了,左边的数字都比他小,右边的数字都比他大
		//排基准数的左边
		quickSort(arr, left, i - 1);
		//排右边
		quickSort(arr, j + 1, right);
		
		
	}
}

复习题:

1. 什么是方法的重载?

“两同一不同”:同一个类、相同方法名;参数列表不同。

如何调用确定的方法:方法名 --> 参数列表

2. 说明Java方法中的参数传递机制的具体体现?

基本数据类型:数据值

引用数据类型:地址值 (含变量的数据类型)

Person p1 =  new Person();  eat();age

User u1 = p1;//编译错误    (逆向思维、反证法)

u1.eat()  u1.age

3. 成员变量和局部变量在声明的位置上、是否有默认初始化值上、是否能有权限修饰符修饰上、内存分配的位置上有何不同?
 *         2.1 在类中声明的位置的不同
 *         属性:直接定义在类的一对{}内
 *         局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
 *         
 *         2.2 关于权限修饰符的不同
 *         属性:可以在声明属性时,指明其权限,使用权限修饰符。
 *             常用的权限修饰符:private、public、缺省、protected  --->封装性
 *             目前,大家声明属性时,都使用缺省就可以了。
 *         局部变量:不可以使用权限修饰符。
 *   
 *         2.3 默认初始化值的情况:
 *         属性:类的属性,根据其类型,都有默认初始化值
 *             整型(byte、short、int、long):0
 *             浮点型(float、double):0.0
 *             字符型(char):0  (或'\u0000')
 *             布尔型(boolean):false
 * 
 *             引用数据类型(类、数组、接口):null
 * 
 *         局部变量:没有默认初始化值。
 *         意味着,我们在调用局部变量之前,一定要显式赋值。
 *         特别地:形参在调用时,我们赋值即可。
 * 
 *         2.4 在内存中加载的位置:
 *         属性:加载到堆空间中(非static)
 *         局部变量:加载到栈空间

4. 谈谈return关键字的使用

① 结束方法 
② 针对于有返回值的方法,return + 返回数据

5. 提供如下代码的内存解析


需要明白以下两点:
1. 内存结构:栈(局部变量)、堆(new出来的结构:对象(非static成员变量)、数组)
2. 变量:成员变量  vs 局部变量(方法内、方法形参、构造器内、构造器形参、代码块内)

七、OOP特征一:封装与隐藏

》  为什么需要封装?封装的作用和含义?
        > 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
        > 我要开车,…
》  我们程序设计追求“高内聚,低耦合”。
        > 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
        > 低耦合 :仅对外暴露少量的方法用于使用。
》  隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说, 把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。

面向对象的特征一:封装与隐藏     3W:what? why? how?


一、问题的引入:

   当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs()) 同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。则需要将属性声明为私有的(private).-->此时,针对于属性就体现了封装性。


  二、封装性的体现:

我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
  
   拓展:封装性的体现:① 如上  ② 不对外暴露的私有的方法  ③ 单例模式   ...

演示示例:

public class AnimalTest {
	public static void main(String[] args) {
		
		Animal a = new Animal();
		a.name = "大黄";
//		a.age = 1;
//		a.legs = 4;//The field Animal.legs is not visible
		
		a.show();
		
//		a.legs = -4;
//		a.setLegs(6);
		a.setLegs(-6);
		
//		a.legs = -4;//The field Animal.legs is not visible
		a.show();
		
		System.out.println(a.name);
		
	}
}


class Animal{
	
	String name;
	private int age;
	private int legs;//腿的个数
	
	//对属性的设置
	public void setLegs(int l){
		if(l >= 0 && l % 2 == 0){
			legs = l;
		}else{
			legs = 0;
//			抛出一个异常(暂时没有讲)
		}
	}
	
	//对属性的获取
	public int getLegs(){
		return legs;
	}
	
	
	public void eat(){
		System.out.println("动物进食");
	}
	
	public void show(){
		System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
	}
	
	//提供关于属性age的get和set方法
	public int getAge(){
		return age;
	}
	public void setAge(int a){
		age = a;
	}
	
}

//private class Dog{
//	
//}


  三、封装性的体现,需要权限修饰符来配合

  1.Java规定的4种权限(从小到大排列):private、缺省、protected 、public 
  2.4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
  3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
     修饰类的话,只能使用:缺省、public


  
  总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。

演示示例:

package com.atguigu.java;

public class Order {
	
	private int orderPrivate;
	int orderDefault;
	public int orderPublic;
	
	
	private void methodPrivate(){
		orderPrivate = 1;
		orderDefault = 2;
		orderPublic = 3;
	}
	void methodDefault(){
		orderPrivate = 1;
		orderDefault = 2;
		orderPublic = 3;
	}
	public void methodPublic(){
		orderPrivate = 1;
		orderDefault = 2;
		orderPublic = 3;
	}
	
}
package com.atguigu.java;

public class OrderTest {
	public static void main(String[] args) {
		
		Order order = new Order();
		
		order.orderDefault = 1;
		order.orderPublic = 2;
		//出了Order类之后,私有的结构就不可以调用了
//		order.orderPrivate = 3;//The field Order.orderPrivate is not visible
		
		
		
		order.methodDefault();
		order.methodPublic();
		//出了Order类之后,私有的结构就不可以调用了
//		order.methodPrivate();//The method methodPrivate() from the type Order is not visible
	}
}
package com.atguigu.java1;

import com.atguigu.java.Order;

public class OrderTest {
	public static void main(String[] args) {
		Order order = new Order();

		order.orderPublic = 2;
		// 出了Order类所属的包之后,私有的结构、缺省声明的结构就不可以调用了
//		order.orderDefault = 1;
		// order.orderPrivate = 3;//The field Order.orderPrivate is not visible

		order.methodPublic();
		// 出了Order类所属的包之后,私有的结构、缺省声明的结构就不可以调用了
//		order.methodDefault();
		// order.methodPrivate();//The method methodPrivate() from the type Order is not visible
	}
}

 小练习:

/*
 * 1.创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
 * 用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。
 * 
 * 2.练习2:
 * 2.1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
 * 2.2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同时初始化对象的age属性值和name属性值。

 * 
 */
public class Person {
	
	private int age;
	private String name;
	
	public Person(){
		age = 18;
	}
	
	public Person(String n,int a){
		name = n;
		age = a;
	}
	
	
	public void setAge(int a){
		if(a < 0 || a > 130){
//			throw new RuntimeException("传入的数据非法!");
			System.out.println("传入的数据非法!");
			return;
		}

		age = a;
		
	}
	
	public int getAge(){
		return age;
	}
	
	//绝对不要这样写!!
//	public int doAge(int a){
//		age = a;
//		return age;
//	}
	
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	
}

/*
 * 在PersonTest类中实例化Person类的对象b,
 * 调用setAge()和getAge()方法,体会Java的封装性。
 * 
 */
public class PersonTest {
	public static void main(String[] args) {
		
		Person p1 = new Person();
//		p1.age = 1;编译不通过
		
		p1.setAge(12);
		
		System.out.println("年龄为:" + p1.getAge());
		
//		p1.doAge(122);
		
		
		Person p2 = new Person("Tom", 21);
		System.out.println("name = " + p2.getName() + ",age = " + p2.getAge());
		
	}
}

八、类的成员之三:构造器

类的结构之三:构造器(或构造方法、constructor)的使用
  construct:建设、建造。  construction:CCB    constructor:建设者

一、构造器的作用:

  1.创建对象
  2.初始化对象的信息

 二、说明:

  1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
  2.定义构造器的格式:权限修饰符  类名(形参列表){}
  3.一个类中定义的多个构造器,彼此构成重载
  4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
  5.一个类中,至少会有一个构造器。
一个形象的例子来比喻构造器:
  如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的 构造器中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。

演示示例:

/*
 * 1.创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
 * 用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。
 * 
 * 2.练习2:
 * 2.1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
 * 2.2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同时初始化对象的age属性值和name属性值。

 * 
 */
public class Person {
	
	private int age;
	private String name;
	
	public Person(){
		age = 18;
	}
	
	public Person(String n,int a){
		name = n;
		age = a;
	}
	
	
	public void setAge(int a){
		if(a < 0 || a > 130){
//			throw new RuntimeException("传入的数据非法!");
			System.out.println("传入的数据非法!");
			return;
		}

		age = a;
		
	}
	
	public int getAge(){
		return age;
	}
	
	//绝对不要这样写!!
//	public int doAge(int a){
//		age = a;
//		return age;
//	}
	
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	
}
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 Person(String n,int a){
		name = n;
		age = a;
	}

	
	//方法
	public void eat(){
		System.out.println("人吃饭");
	}
	
	public void study(){
		System.out.println("人可以学习");
	}
	
}

练习题:

1.

/*
 * 1.创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
 * 用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。
 * 
 * 2.练习2:
 * 2.1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
 * 2.2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同时初始化对象的age属性值和name属性值。

 * 
 */
public class Person {
	
	private int age;
	private String name;
	
	public Person(){
		age = 18;
	}
	
	public Person(String n,int a){
		name = n;
		age = a;
	}
	
	
	public void setAge(int a){
		if(a < 0 || a > 130){
//			throw new RuntimeException("传入的数据非法!");
			System.out.println("传入的数据非法!");
			return;
		}

		age = a;
		
	}
	
	public int getAge(){
		return age;
	}
	
	//绝对不要这样写!!
//	public int doAge(int a){
//		age = a;
//		return age;
//	}
	
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	
}
/*
 * 在PersonTest类中实例化Person类的对象b,
 * 调用setAge()和getAge()方法,体会Java的封装性。
 * 
 */
public class PersonTest {
	public static void main(String[] args) {
		
		Person p1 = new Person();
//		p1.age = 1;编译不通过
		
		p1.setAge(12);
		
		System.out.println("年龄为:" + p1.getAge());
		
//		p1.doAge(122);
		
		
		Person p2 = new Person("Tom", 21);
		System.out.println("name = " + p2.getName() + ",age = " + p2.getAge());
		
	}
}

2.

/*
 * 编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。
 * 此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
 */
public class TriAngle { //angle:角    angel:天使
	
	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;
	}
	
}
public class TriAngleTest {
	public static void main(String[] args) {
		
		TriAngle t1 = new TriAngle();
		t1.setBase(2.0);
		t1.setHeight(2.4);
//		t1.base = 2.5;//The field TriAngle.base is not visible
//		t1.height = 4.3;
		System.out.println("base : " + t1.getBase() + ",height : " + t1.getHeight());
		
		TriAngle t2 = new TriAngle(5.1,5.6);
		System.out.println("base : " + t2.getBase() + ",height : " + t2.getHeight());
	}
}

总结:属性赋值的先后顺序

  ① 默认初始化
  ② 显式初始化
  ③ 构造器中初始化
  ④ 通过"对象.方法" 或 "对象.属性"的方式,赋值
  以上操作的先后顺序:① - ② - ③ - ④  

演示示例:

public class UserTest {
	public static void main(String[] args) {
		User u = new User();
		
		System.out.println(u.age);
		
		User u1 = new User(2);
		
		u1.setAge(3);
		u1.setAge(5);
		
		System.out.println(u1.age);
	}
}

class User{
	String name;
	int age = 1;
	
	public User(){
		
	}
	
	public User(int a){
		age = a;
	}
	
	public void setAge(int a){
		age = a;
	}
	
}

拓展知识:JavaBean

JavaBean是一种Java语言写成的可重用组件。

    所谓JavaBean,是指符合如下标准的Java类:
        >类是公共的
        >有一个无参的公共的构造器
        >有属性,且有对应的get、set方法

示例:

public class Customer {
	
	private int id;
	private String name;
	
	public Customer(){
		
	}
	
	public void setId(int i){
		id = i;
	}
	public int getId(){
		return id;
	}
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	
}

拓展知识:UML类图

九、关键字:this

 this关键字的使用:

1.this可以用来修饰、调用:属性、方法、构造器

2.this修饰属性和方法:

   this理解为:当前对象  或 当前正在创建的对象
   2.1  在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
   2.2 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。但是,通常情况下,我们都选择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。

3. 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初始化时,需要考虑如下的1,2,3,4...(共40行代码)";
		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;
		//Person初始化时,需要考虑如下的1,2,3,4...(共40行代码)
	}
	
	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;
	}
	
	public void eat(){
		System.out.println("人吃饭");
		this.study();
	}
	public void study(){
		System.out.println("人学习");
	}
	
}

练习题:

1.

public class Boy {
	private String name;
	private int age;
	
	public Boy() {
		
	}
	
	public Boy(String name) {
		this.name = name;
	}

	public Boy(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public void marry(Girl girl){
		System.out.println("我想娶" + girl.getName());
	}
	
	public void shout(){
		if(this.age >= 22){
			System.out.println("你可以去合法登记结婚了!");
		}else{
			System.out.println("先多谈谈恋爱~~");
		}
		
	}
}

public class Girl {
	
	private String name;
	private int age;
	
	public Girl() {

	}
	public Girl(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void marry(Boy boy){
		System.out.println("我想嫁给" + boy.getName());
		boy.marry(this);
	}
	
	/**
	 * 
	 * @Description 比较两个对象的大小
	 * @author shkstart
	 * @date 2019年1月18日下午4:02:09
	 * @param girl
	 * @return  正数:当前对象大;  负数:当前对象小  ; 0:当前对象与形参对象相等
	 */
	public int compare(Girl girl){
//		if(this.age > girl.age){
//			return 1;
//		}else if(this.age < girl.age){
//			return -1;
//		}else{
//			return 0;
//		}
		
		return this.age - girl.age;
		
	}
	
}
public class BoyGirlTest {
	public static void main(String[] args) {
		
		Boy boy = new Boy("罗密欧", 21);
		boy.shout();
		
		Girl girl = new Girl("朱丽叶", 18);
		girl.marry(boy);
		
		Girl girl1 = new Girl("祝英台",19);
		int compare = girl.compare(girl1);
		if(compare > 0){
			System.out.println(girl.getName() + "大");
		}else if(compare < 0){
			System.out.println(girl1.getName() + "大");
		}else{
			System.out.println("一样大");
		}
		
	}
}

2. 实验一:

1、写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性:
账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter方法),取款方法 withdraw(),存款方法 deposit()。
Account
private int id
private double balance
private double annualInterestRate
public 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 中,需要判断用户余额是否能够满足提款数额的要求,如果不
能,应给出提示。


2. 创建 Customer 类。
Customer
private String firstName
private String lastName
private Account account
public Customer(String f,String l)
public String getFirstName()
public String getLastName()
public Account getAccount()
public void setAccount(Account account)
a. 声明三个私有对象属性:firstName、lastName 和 account。
b. 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f 和 l)
c. 声明两个公有存取器来访问该对象属性,方法 getFirstName 和 getLastName 返回相应的属性。
d. 声明 setAccount 方法来对 account 属性赋值。
e. 声明 getAccount 方法以获取 account 属性。


3.写一个测试程序。
(1) 创建一个 Customer ,名字叫 Jane Smith, 他有一个账号为 1000,余额为 2000 元,
年利率为 1.23% 的账户。
(2) 对 Jane Smith 操作。
存入 100 元,再取出 960 元。再取出 2000 元。
打印出 Jane Smith 的基本信息
成功存入 :100.0
成功取出:960.0
余额不足,取款失败
Customer [Smith, Jane] has a account: id is 1000, annualInterestRate is  1.23% , balance is 1140.0

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 (balance > 0 && balance >= amount) {
            balance -= amount;
            System.out.println("取钱成功,取出:" + amount + "元");
            return;
        }
        System.out.println("取钱失败,您的账户当前余额为:" + balance + " < " + amount);
    }

    public void deposit (double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("存钱成功,存入:" + amount + "元");
            return;
        }
        System.out.println("请输入合理的数额!");
    }
}
public class Customer {
    private String firstName;
    private String lastName;
    private Account account;

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }
}
public class Test {
    public static void main(String[] args) {
        Customer customer = new Customer("Jane", "Smith");
        Account account = new Account(1000, 2000, 0.0123);

        customer.setAccount(account);
        customer.getAccount().deposit(100);
        customer.getAccount().withdraw(960);
        customer.getAccount().withdraw(2000);

        System.out.println("Customer ["+customer.getLastName()+","+customer.getFirstName()+"] has a account:id is "
        + customer.getAccount().getId()+",annualInterestRate is "+customer.getAccount().getAnnualInterestRate()*100+"%,"
        +"balance is "+customer.getAccount().getBalance());

    }
}

3. 实验二:

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("存钱成功,存入:" + amt + "元");
            return;
        }
        System.out.println("存钱金额不能为非负数!");
    }
    public void withdraw(double amt){
        if (amt > 0 && amt <= balance){
            balance -= amt;
            System.out.println("取钱成功,取出:" + amt + "元");
        }
    }

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }
}
public class Customer {
    private String firstName;
    private String lastName;
    private Account account;

    public Customer(String f, String l){
        firstName = f;
        lastName = l;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account acct) {
        account = acct;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", account=" + account +
                '}';
    }

}
public class Bank {
    private Customer customers[] = new Customer[2];
    private int numberOfCustomer;

    public Bank() {
    }

    public void addCustomer(String f, String l) {
        customers[numberOfCustomer++] = new Customer(f, l);
    }

    public int getNumberOfCustomer() {
        return numberOfCustomer;
    }

    public Customer getCustomer(int index) {
        if (index >= 0 && index < numberOfCustomer) {
            return customers[index];
        }
        return null;
    }
}
public class BankTest {
    public static void main(String[] args) {
        Bank bank = new Bank();
        bank.addCustomer("Jane", "Smith");
        bank.addCustomer("Bob", "Bookie");
//        bank.addCustomer("Amy", "Sties");
        Account account = new Account(2000);
        System.out.println( bank.getCustomer(3));
        bank.getCustomer(0).setAccount(new Account(1000));
        bank.getCustomer(1).setAccount(account);
        bank.getCustomer(1).getAccount().deposit(1000);
        bank.getCustomer(1).getAccount().withdraw(500);
        System.out.println(bank.getCustomer(1).getAccount().getBalance());
        System.out.println(bank.getNumberOfCustomer());
        System.out.println(bank.getCustomer(1));

        System.out.println(bank.getCustomer(0));
    }
}

十、关键字:package、import


  一、package关键字的使用

  1.为了更好的实现项目中类的管理,提供包的概念
  2.使用package声明类或接口所属的包,声明在源文件的首行
  3.包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”
  4.每"."一次,就代表一层文件目录。
  补充:同一个包下,不能命名同名的接口、类。
             不同的包下,可以命名同名的接口、类。

二、import关键字的使用

   import:导入
  1. 在源文件中显式的使用import结构导入指定包下的类、接口
  2. 声明在包的声明和类的声明之间
  3. 如果需要导入多个结构,则并列写出即可
  4. 可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构
  5. 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
  6. 如果使用的类或接口是本包下定义的,则可以省略import结构
  7. 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
  8. 使用"xxx.*"方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
  9. import static:导入指定类或接口中的静态结构:属性或方法。 

演示示例:

public class PackageImportTest {
	public static void main(String[] args) {
		
		String info = Arrays.toString(new int[]{1,2,3});
		
		Bank bank = new Bank();
		
		ArrayList list = new ArrayList();
		HashMap map = new HashMap();
		
		Scanner s = null;
		
		System.out.println("hello!");
		
		Person p = new Person();
		
		Account acct = new Account(1000);
		//全类名的方式显示
		com.atguigu.exer3.Account acct1 = new com.atguigu.exer3.Account(1000,2000,0.0123);
		
		Date date = new Date();
		java.sql.Date date1 = new java.sql.Date(5243523532535L);
		
		Dog dog = new Dog();
		
		Field field = null;
		
		out.println("hello");
		
		long num = round(123.434);
	}
}

 

 

每日一考练习题

1.构造器的作用是什么?使用中有哪些注意点(>=3条)

        ①创建对象 ②初始化对象结构

2.关于类的属性的赋值,有几种赋值的方式。谈谈赋值的先后顺序

        默认初始化-显式初始化-构造器中初始化-对象.方法 或 对象.属性 给属性赋值

3.this关键字可以用来调用哪些结构,简单说明一下其使用。

        this:属性、方法、构造器

        this:理解为当前对象,当前正在创建的对象

4. Java中目前学习涉及到的四种权限修饰符都有什么?并说明各自的权限范围

private int age;

private void eat(){}

5. 创建Circle类,提供私有的radius属性,提供相应的get和set方法,提供求圆面积的方法。

private double radius;

public void setRadius(double radius){

      this.radius = radius;

}

public double getRadius(){

      return radius;

}

public double findArea(){

      return 3.14 * getRadius() * radius;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值