一文带你深入理解【Java基础】· 面向对象编程(上)②重载、封装、构造器、this、package和import

写在前面


        Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误不足之处,请多多指正!谢谢大家!!!

        如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!


目录

写在前面

1. 再谈方法

1.1 方法的重载(overload)

1.2 可变个数的形参

1.3 方法参数的值传递机制

1.4 递归方法

 2. 面向对象特征之一:封装与隐藏

2.1 封装与隐藏

2.2 信息的封装和隐藏

2.3 四种访问权限修饰符

3. 类的成员之三:构造器(或构造方法)

3.1 构造器的特征和作用

3.2 练习

3.3 属性赋值过程

3.4 JavaBean

4. this关键字的使用

4.1 this是什么?

5.关键字:package、import的使用

5.1 package的使用

5.2 import的使用

结语


【往期回顾】

一文带你深入理解【Java基础】· 面向对象编程(上)①面向对象的理解、类和对象、对象的创建使用和属性

一文带你深入理解【Java基础】· 数组

一文带你深入理解【Java基础】· Java基本语法:程序流程控制

一文带你深入理解【Java基础】· Java基本语法:运算符

一文带你深入理解【Java基础】 · Java基本语法:变量

一文带你深入理解【Java基础】 · Java语言概述


【习题总结】

【Java基础】· 面向对象编程(上)习题详解


1. 再谈方法


1.1 方法的重载(overload)

重载的概念
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数
类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类
型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//返回两个整数的和
int add(int x,int y){
    return x+y;
}
//返回三个整数的和
int add(int x,int y,int z){
    return x+y+z;
}
//返回两个小数的和
double add(double x,double y){
    return x+y;
}
使用重载方法,可以为编程带来方便。 例如,System.out.println() 方法就是典型的重载方法,其内部的声明形式如下:
public void println(byte x)
public void println(short x)
public void println(int x)
public void println(long x)
public void println(float x)
public void println(double x)
public void println(char x)
public void println(double x)
public void println()
……

练习:

1. 编写程序,定义三个重载方法并调用。方法名为 mOL
三个方法分别接收一个 int 参数、两个 int 参数、一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。在主类的main () 方法中分别用参数区别调用三个方法。
2. 定义三个重载方法 max() ,第一个方法求两个 int 值中的最大值,第二个方法求两个double 值中的最大值,第三个方法求三个 double 值中的最大值,并分别调用三个方法。
/*
 * 1.编写程序,定义三个重载方法并调用。方法名为mOL。
	三个方法分别接收一个int参数、两个int参数、一个字符串参数。
	分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
	在主类的main ()方法中分别用参数区别调用三个方法。
	
	2.定义三个重载方法max(),
	第一个方法求两个int值中的最大值,
	第二个方法求两个double值中的最大值,
	第三个方法求三个double值中的最大值,
	并分别调用三个方法。
 */
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;
	}
}

自定义数组的工具类及其使用:

/*
 * 自定义数组的工具类
 * 
 */
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 void reverse(String[] arr){
	}

	// 复制数组
	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;
					//错误的:
//					swap(arr[j],arr[j + 1]);
					//正确的:
					swap(arr,j,j + 1);
				}
			}
		}
	}
	
	//错误的:交换数组中指定两个位置元素的值
//	public void swap(int i,int j){
//		int temp = i;
//		i = j;
//		j = temp;
//	}
	//正确的:交换数组中指定两个位置元素的值
	public void swap(int[] arr,int i,int j){
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = 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;//返回一个负数,表示没有找到
	}
}
public class ArrayUtilTest {
	public static void main(String[] args) {
		ArrayUtil util = new ArrayUtil();
		int[] arr = new int[]{32,34,32,5,3,54,654,-98,0,-53,5};
		System.out.println("最大值为:" + util.getMax(arr));
		System.out.println("最小值为:" + util.getMin(arr));
		System.out.println("排序前:");
		util.print(arr);
		util.sort(arr);
		System.out.println("排序后:");
		util.print(arr);
		util.reverse(arr);
		System.out.println("数组的总和为:" + util.getSum(arr));
		System.out.println("数组的平均值为:" + util.getAvg(arr));
		//其他方法类似……
	}
}

方法的重载:

/*
 * 方法的重载(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 可变个数的形参

JavaSE 5.0 中提供了 Varargs( variable number of arguments ) 机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。
//JDK 5.0 以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0 :采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String…books);
说明:
1. 声明格式: 方法名 ( 参数的类型名 ... 参数名 )
2. 可变参数:方法参数部分指定类型的参数个数是可变多个: 0 个, 1 个或多个
3. 可变个数形参的方法与同名的方法之间,彼此构成重载
4. 可变参数方法的使用与方法参数部分使用数组是一致的
5. 方法的参数部分有可变形参,需要放在形参声明的最后
6. 在一个方法的形参位置,最多只能声明一个可变个数形参
/*
 * 可变个数形参的方法
 * 
 * 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){
//	}
}


1.3 方法参数的值传递机制

方法,必须由其所在类或对象调用才有意义。若方法含有参数:
  • 形参:方法声明时的参数
  • 实参:方法调用时实际传给形参的参数值
Java 的实参值如何传入方法呢?
Java 里方法的参数传递方式只有一种: 值传递 。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参

变量的赋值:

/*
 * 关于变量的赋值:
 *  如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
 *  如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
 */
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);//10 10
		n = 20;
		System.out.println("m = " + m + ", n = " + n);//10 20
		
		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);//1001
		o2.orderId = 1002;
		System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);//1002
	}
}

class Order{
	int orderId;
}

方法形参的传递机制:

/*
 * 方法的形参的传递机制:值传递
 * 1.形参:方法定义时,声明的小括号内的参数
 *   实参:方法调用时,实际传递给形参的数据
 * 2.值传递机制:
 * 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
 * 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
 */
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 )定义一个 Circle 类,包含一个 double 型的 radius 属性代表圆的半径,一个findArea()方法返回圆的面积。
(2 )定义一个类 PassObject ,在类中定义一个方法 printAreas() ,该方法的定义 如下:public void printAreas(Circle c, int time)
printAreas 方法中打印输出 1 time 之间的每个整数半径值,以及对应的面积。
例如, times 5 ,则输出半径 1 2 3 4 5 ,以及对应的圆面积。
(3 )在 main 方法中调用 printAreas() 方法,调用完毕后输出当前半径值。
/*
 * 定义一个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;
	}
}


1.4 递归方法

  • 递归方法:一个方法体内调用它自身。
  • 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
  • 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
/*
 * 递归方法的使用(了解)
 * 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);
	}

	// 例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);
		}
	}
}

 2. 面向对象特征之一:封装与隐藏


2.1 封装与隐藏

为什么需要封装?封装的作用和含义?

  • 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?不需要!我们只要懂得操作即可!

程序设计追求“高内聚,低耦合”。

  • 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
  • 低耦合 :仅对外暴露少量的方法用于使用。
  • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。

2.2 信息的封装和隐藏

Java 中通过将数据声明为私有的 (private) ,再提供公共的( public )方法: getXxx() setXxx() 实现对该属性的操作,以实现下述目的:
  • 隐藏一个类中不需要对外提供的实现细节;
  • 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
  • 便于修改,增强代码的可维护性;

2.3 四种访问权限修饰符

Java 权限修饰符 public protected ( 缺省 ) private 置于 类的成员 定义前,用来限定对象对该类成员的访问权限。
对于 class 的权限修饰只可以用 public default( 缺省 )
  • public类可以在任意地方被访问。
  • default类只可以被同一个包内部的类访问。

/*
 * 面向对象的特征一:封装与隐藏     3W:what? why? how?
 * 一、问题的引入:
 *  当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到
 *  属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值
 *  加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs())
 *  同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。则需要将属性声明为私有的(private).
 *  -->此时,针对于属性就体现了封装性。
 * 
 * 二、封装性的体现:
 * 我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
 * 
 *  拓展:封装性的体现:① 如上  ② 不对外暴露的私有的方法  ③ 单例模式   ...
 *  
 * 
 * 三、封装性的体现,需要权限修饰符来配合。
 * 1.Java规定的4种权限(从小到大排列):private、缺省、protected 、public 
 * 2.4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
 * 3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
 *        修饰类的话,只能使用:缺省、public
 * 
 * 总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
 * 
 */
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{
//
// }

四种权限修饰符的使用:

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;
	}
}
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
	}
}
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
	}
}


3. 类的成员之三:构造器(或构造方法)


3.1 构造器的特征和作用

构造器的特征
  • 它具有与类相同的名称
  • 它不声明返回值类型。(与声明为void不同)
  • 不能被staticfinalsynchronizedabstractnative修饰,不能有return语句返回值
构造器的作用 创建对象;给对象进行初始化
  • 如:Order o = new Order(); Person p = new Person(“Peter”,15);
  • 如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的构造器中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。
语法格式:
修饰符 类名 ( 参数列表 ) {
        初始化语句;
}
根据参数不同,构造器可以分为如下两类:
  • 隐式无参构造器(系统默认提供)
  • 显式定义一个或多个构造器(无参、有参)

注 意:

  • Java语言中,每个类都至少有一个构造器
  • 默认构造器的修饰符与所属类的修饰符一致
  • 一旦显式定义了构造器,则系统不再提供默认构造器
  • 一个类可以创建多个重载的构造器
  • 父类的构造器不可被子类继承
/*
 * 类的结构之三:构造器(或构造方法、constructor)的使用
 * construct:建设、建造。  construction:CCB    constructor:建设者
 * 
 * 一、构造器的作用:
 * 1.创建对象
 * 2.初始化对象的信息
 * 
 * 二、说明:
 * 1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
 * 2.定义构造器的格式:权限修饰符  类名(形参列表){}
 * 3.一个类中定义的多个构造器,彼此构成重载
 * 4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
 * 5.一个类中,至少会有一个构造器。
 */
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("人可以学习");
	}
}


3.2 练习

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

/*
 * 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());
	}
}
3. 编写两个类, TriAngle TriAngleTest ,其中 TriAngle 类中声明私有的底
边长 base 和高 height ,同时声明公共方法访问私有变量。此外,提供类
必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
/*
 * 编写两个类,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());
	}
}


3.3 属性赋值过程

截止到目前,我们讲到了很多位置都可以对类的属性赋值。现总结这几个位置,并指明赋值的先后顺序。
赋值的位置:
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过“对象 . 属性“或“对象 . 方法”的方式赋值
赋值的先后顺序
- - -

3.4 JavaBean

  • JavaBean是一种Java语言写成的可重用组件。
  • 所谓javaBean,是指符合如下标准的Java类:
    • 类是公共的
    • 有一个无参的公共的构造器
    • 有属性,且有对应的getset方法
  • 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBeanapplet程序或者应用来使用这些对象。用户可以认为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;
	}
}


4. this关键字的使用


4.1 this是什么?

Java 中, this 关键字比较难理解,它的作用和其词义很接近。
  • 它在方法内部使用,即这个方法所属对象的引用;
  • 它在构造器内部使用,表示该构造器正在初始化的对象。
  • this 可以调用类的属性、方法和构造器
什么时候使用 this 关键字呢?
  • 当在方法内需要用到调用该方法的对象时,就用this具体的:我们可以用this来区分属性局部变量
  • 比如:this.name = name;
使用 this ,调用属性、方法:
1. 在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this, 增强程序的阅读性。不过,通常我们都习惯省略this
2. 当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this
表明该变量是类的成员变量。
3. 使用 this 访问属性和方法时,如果在本类中未找到,会从父类中查找。
4.this 可以作为一个类中构造器相互调用的特殊格式。
注意:
  • 可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器!
  • 确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
  • 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(形参列表)"
  • "this(形参列表)"必须声明在类的构造器的首行!
  • 在类的一个构造器中,最多只能声明一个"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("人学习");
	}
}

5.关键字:package、import的使用


5.1 package的使用

package 语句作为 Java 源文件的第一条语句,指明该文件中定义的类所在的包。( 若缺省该语句,则指定为无名包 ) 。它的格式为:
package 顶层包名 . 子包名 ;
举例:
pack1\pack2\PackageTest.java
package pack1.pack2; //指定类PackageTest属于包pack1.pack2
public class PackageTest{
    public void display(){
        System.out.println("in method display()");
    }
}
包对应于文件系统的目录, package 语句中,用 “ . ” 来指明包 ( 目录 ) 的层次;
包通常用小写单词标识。通常使用所在公司域名的倒置: com.atguigu.xxx
包的作用:
  • 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式
  • 包可以包含类和子包,划分项目层次,便于管理
  • 解决类命名冲突的问题
  • 控制访问权限

JDK中主要的包介绍

1. java.lang ---- 包含一些 Java 语言的核心类,如 String Math Integer System和 Thread,提供常用功能
2. java.net ---- 包含执行与网络相关的操作的类和接口。
3. java.io ---- 包含能提供多种输入 / 输出功能的类。
4. java.util ---- 包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
5. java.text ---- 包含了一些 java 格式化相关的类
6. java.sql ---- 包含了 java 进行 JDBC 数据库编程的相关类 / 接口
7. java.awt ---- 包含了构成抽象窗口工具集( abstract window toolkits )的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI) B/S C/S

5.2 import的使用

为使用定义在不同包中的 Java 类,需用 import 语句来引入指定包层次下所需要的类或全部类(.*) import 语句告诉编译器到哪里去寻找类。
语法格式:
import 包名 . 类名 ;
注意:
1. 在源文件中使用 import 显式的导入指定包下的类或接口
2. 声明在包的声明和类的声明之间。
3. 如果需要导入多个类或接口,那么就并列显式多个 import 语句即可
4. 举例:可以使用 java.util.* 的方式,一次性导入 util 包下所有的类或接口。
5. 如果导入的类或接口是 java.lang 包下的,或者是当前包下的,则可以省略此 import 语句。
6. 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
是哪个类。
7. 如果已经导入 java.a 包下的类。那么如果需要使用 a 包的子包下的类的话,仍然需要导入。
8. import static 组合的使用:调用指定类或接口下的静态的属性或方法
import java.lang.reflect.Field;
import java.util.*;

import com.atguigu.exer4.Account;
import com.atguigu.exer4.Bank;
import com.atguigu.java2.java3.Dog;

import static java.lang.System.*;
import static java.lang.Math.*;

/*
 * 一、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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麟-小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值