JavaSe基础XX07——面向对象

*this关键字

问题的引出:

package testobject;

class Person {
	private String name;

	Person(String name) {
		name = name; // 问题的引出,name是局部变量,都在栈内存中,不会去访问堆内存中的name,
						// 因此不会对对象中的name进行赋值操作。

	}

	void speack() {
		System.out.println("name:" + name);
	}
}

public class TestObject {

	public static void main(String[] args) {
		Person p = new Person("Jack");
		p.speack();
	}

}


内存解析:



*this的使用场景及细节

回顾:构造函数可以访问一般函数,而一般函数是不能访问构造函数的(除非新建对象的时候),那构造函数怎么可以访问构造函数呢?

注:一个类中所有的成员要想使用都得用对象来调用(除了静态变量)。一般都是省略了this.

分析:

package testobject;

class Person {
	private String name;
	private int age;

	Person(String name) {
		this.name = name;
	}

	Person(String name, int age) {
		this.name = name;
		// 分析:这一句与上面Person(Stringname)这个构造函数的功能一样,因此为了提高函数的重用性,
		// 我们可以来在这个构造函数调用上面Person(String name)这个构造函数.
		// 但是应该怎么调用?
		// Person(name); 如果直接写这句,是不能实现这样的功能的,因为这句的含义其实是 this.Person(name);
		// 而Person(name)本身就是为了初始化对象来用的,前面如果再加上this,就有些说不通了[this是指对象,但都还没有用Person来初始化它,
		// 又怎么能调用Person(name)呢?]
		// 因此正确的调用构造函数的方法应该为:
		// this(name);
		this.age = age;
	}

	void speack() {
		System.out.println(name + "..." + age);
	}
}

public class TestObject {

	public static void main(String[] args) {
		Person p = new Person("Jack", 10);
		p.speack();
	}

}
我们来画个上例的内存示意图:

1.




2.


所以this还有这样的功能:在构造函数调用其他构造函数,只能定义在构造函数的第一行。【因为初始化函数必须先执行】

细节:

Person(String name, int age) {
		this.age = age;
		this(name);//编译出错:Constructor call must be the first statement in a constructor
	}


*this关键字的基本应用

this代表本类对象

package testobject;

class Person {
	private String name;
	private int age;

	Person(String name) {
		this.name = name;
	}

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

	void speack() {
		System.out.println(name + "..." + age);
	}

	/* 判断是否同龄人 */
	public boolean compare(Person p) {
		if(this.age == p.age)//这句也可以写成if(age == p.age) 因为在栈内存中,没有与age同名的局部变量,
							//但是为了提高阅读性,建议写成this.age == p.age
			return true;
		else 	
			return false;
		
		/*
		 判断语句简洁些:
		 1.三目运算符
		 	return (this.age == p.age)?true:false;
		 2.更为简洁的
		 	return this.age == p.age;
		 */
	}
}

public class TestObject {

	public static void main(String[] args) {
		Person p1 = new Person("Jack", 10);
		Person p2 = new Person("Lisa", 12);
		boolean b = p1.compare(p2);
		System.out.println(b);
	}

}

====================================================================================================================================

*另一个关键字:static——数据共享


static本身即是关键字也是修饰符,那它到底什么时候用,怎么用呢?

问题引入:

我们创建对象,对象是来封装数据的,但是当数据中有所有对象共同的同样值的数据时,这个时候再创建对象的时候,就会很占内存的。


成员被static修饰之后,有什么好处?

因为static修饰之后,数据就变成了共享数据,所以该数据要在对象生成前要先有。

被static修饰的数据,不仅可以被对象调用使用,而且也可以直接被类名来调用使用。


被static修饰的变量叫做静态变量,它的好处有:1.有两种调用方式了 2.可以不用创建对象,就能使用了。




静态变量就不要称作成员变量。

实例变量:实例就是对象。

	private String name;
	private int age;	//实例变量<------->成员变量
	static private String country = "CN";//静态变量<------>类变量[注:和类类型变量不一样]


虚拟机结束了,类就会消失。[后期会讲到:类本身就是对象。]

虚拟机在加载类的时候,如果加载太多了,会有垃圾回收机制,释放很长时间不在用的类。

静态变量不存在于堆内存中,因为堆内存中不可能单独存放一个数据,它只能存实体。

那静态变量会不会存在栈中呢?不会。栈内存一般生命周期比较短,而且栈里面的数据是随着方法的加载而出现的。

那静态变量在哪呢?

内存分类:

1.本地方法区---->for 系统方法

2.寄存器---->for CPU

3.方法区

4.堆

5.栈


方法就放在方法区。

静态变量存在方法区的静态区中,所以也叫对象的共享数据。

总结:


*静态使用的一些细节:
静态方法:public static void speak(){}

error:无法总静态上下文中引用非静态变量 为什么?

因为静态方法是先存在的,先于对象的创建,成员变量是在对象创建的时候,存在的。

静态方法可以用类名来访问。




在访问非静态变量时,省略了this,在访问静态变量时,省略了类名。


*main函数解析





*静态成员的内存解析

1.程序被加载到内存是,当在dos界面执行java语句开始的



*什么时候使用静态呢?


*静态代码块


静态代码块:随着类的加载,而执行。而且只执行一次。


作用:给类初始化。

不是所有类都是用构造函数初始化的。

*构造代码块

构造函数不止是定义数据


定义在类中的代码块:称作构造代码块,和对象有关,创建几个对象,运行几次。是给所有对象初始化用的。

而构造函数是给对象有针对性的初始化。


定义在函数里面的代码块叫做局部代码块。

package testobject;

class Person {
	private String name;
	{
		cry();
	}

	Person() {
		name = "baby";
		// cry();
	}

	Person(String name) {
		this.name = name;
		// cry();
	}

	public void cry() {
		System.out.println("wawa...");
	}

	public void speak() {
		System.out.println("name:" + name);
	}
}

public class TestObject {

	public static void main(String[] args) {
		Person p1 = new Person();
		p1.speak();
		Person p2 = new Person("Jack");
		p2.speak();
	}

}

*数组工具类中static的使用

练习:

求数组的最大值=========[del *.class],Java编辑器会检查当前类是否用到其他类,如果检查到有的话,java编译器会自动给出编译。

1.

public class ArrayMain {

	public static void main(String[] args) {
		int[] arr = { 12, 47, 98, 3, 7, 78 };
		int maxIndex = 0;
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > arr[maxIndex])
				maxIndex = i;
		}
		System.out.println("Max:" + arr[maxIndex]);
	}

}

2. 方法1,是面向过程的,而且如果要对多个数组进行求最大值,那么就要写很多重复代码,不推荐,接下来做下完善。

public class ArrayMain {

	public static void main(String[] args) {
		int[] arr = { 12, 147, 98, 3, 7, 78 };
		int max = getMax(arr);
		System.out.println("Max:" + max);
	}

	public static int getMax(int[] arr) {
		int maxIndex = 0;
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > arr[maxIndex])
				maxIndex = i;
		}
		return arr[maxIndex];
	}
}

3.但是上面的如果是其他类也想用的话,就不是很好了,所以我们推荐将这些都封装在一个工具类中,做如下修改:

ArrayMain.java文件代码:

public class ArrayMain {

	public static void main(String[] args) {
		int[] arr = { 12, 147, 98, 3, 347, 78 };
		ArrayTools tool = new ArrayTools();
		int max = tool.getMax(arr);
		System.out.println("Max:" + max);

		tool.selectSort(arr);
		tool.print(arr);

		int index = tool.getIndex(arr, 31);
		System.out.println("index:" + index);

	}
}

ArrayTools工具类:

package array;

public class ArrayTools {
	public int getMax(int[] arr) {
		int maxIndex = 0;
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > arr[maxIndex])
				maxIndex = i;
		}
		return arr[maxIndex];
	}

	public int getIndex(int[] arr, int key) {
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == key)
				return i;
		}
		return -1;
	}

	public void selectSort(int[] arr) {
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; j < arr.length; j++)
				if (arr[i] > arr[j])
					swap(arr, i, j);
		}
	}

	private void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[j] = arr[j];
		arr[j] = temp;
	}

	public void print(int[] arr) {
		for (int n : arr)
			System.out.print(n + ",");
		System.out.println();
	}

}

4.尽管上面很好,但还是存在问题

观察ArrayTool里面的代码可以看出里面没有任何的成员变量,也就是说这个工具类中的方法都没有访问到任何成员变量数据,因此我们就可以对方法添加静态修饰词static。

这样的话,在main函数中,就可以不用生成对象,再用对象来调用方法了,这样就会节省内存空间。

修改代码如下:

main函数中:

package array;

public class ArrayMain {

	public static void main(String[] args) {
		int[] arr = { 12, 147, 98, 3, 347, 78 };
		// ArrayTools tool = new ArrayTools();
		int max = ArrayTools.getMax(arr);
		System.out.println("Max:" + max);

		ArrayTools.selectSort(arr);
		ArrayTools.print(arr);

		int index = ArrayTools.getIndex(arr, 31);
		System.out.println("index:" + index);

	}
}

工具类函数中:

package array;

public class ArrayTools {
	public static int getMax(int[] arr) {
		int maxIndex = 0;
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > arr[maxIndex])
				maxIndex = i;
		}
		return arr[maxIndex];
	}

	public static int getIndex(int[] arr, int key) {
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == key)
				return i;
		}
		return -1;
	}

	public static void selectSort(int[] arr) {
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; j < arr.length; j++)
				if (arr[i] > arr[j])
					swap(arr, i, j);
		}
	}

	private static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[j] = arr[j];
		arr[j] = temp;
	}

	public static void print(int[] arr) {
		for (int n : arr)
			System.out.print(n + ",");
		System.out.println();
	}

}

5.这样操作固然可以节省空间,但是当我们把这个工具类,交给别人使用的时候,怎么防止他人会使用ArrayTools tool = new ArrayTools();这个方法创建个对象,之后在用对象进行操作呢,这样一样还是会浪费空间的,还是没有达到我们的目的。怎样操作可以防止呢?也就是说如何强制限制用户不让他创建这个对象。

方法很简答,直接在工具类的方法中复写构造函数并设置为私有。

public class ArrayTools {
	private ArrayTools() {
	}//构造函数私有化
}

*数组工具类——注释文档

文档注释javadoc













怎么使用呢?





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值