类基础

类的封装性(private)

封装属性:private 属性类型 属性名

封装方法:private 方法返回类型 方法名称(参数)


注意:
用private声明的属性或方法只能在其类的内部被调用,而不能在类的外部被调用。


匿名对象:

可以简单的理解为只使用一次的对象,即没有任何一个具体的对象名称引用它。

System.out.println(new Person().talk());

new Person()声明的对象并没有赋给任何一个Person类对象的引用,所以此对象只使用了一次,之后就会被Java的垃圾收集器回收。


构造方法:

构造方法所完成的主要工作是帮助新创建的对象赋初值

1、它具有与类名相同的名称
2、它没有返回值


对象的比较

有两种方式可用于对象间的比较,它们是“= =”运算符与equals()方法,

“= =”操作符用于比较两个对象的内存地址值是否相等,

equals()方法用于比较两个对象的内容是否一致。

问题:

下面两种String对象的声明方式到底有什么不同?

String str1 = new String("java");
String str2 = "java";

01 public class StringDemo
02 {
03 public static void main(String[] args)
04 {
05 String str1 = "java" ;
06 String str2 = new String("java") ;
07 String str3 = "java" ;
08 System.out.println("str1 == str2 ? --- > "+(str1==str2)) ;
09 System.out.println("str1 == str3 ? --- > "+(str1==str3)) ;
10 System.out.println("str3 == str2 ? --- > "+(str3==str2)) ;
11 }
12 }
输出结果:
str1 == str2 ? --- > false
str1 == str3 ? --- > true
str3 == str2 ? --- > false
由程序输出结果可以发现,str1与str3相等,这是为什么呢?上面提到过"=="是用来比较内存地址值得。现在str1与str3相等,则证明str1与str3是指向同一个内存空间的。可以用下图来说明:


由图中可以看出“java”这个字符串在内存中开辟的一个空间,而str1与str3又同时指向同一个内存空间,所以即使str1与str3虽然是分开声明的,但最终却指向了同一内存空间,而str2是用new关键字来开辟的空间,所以单独占有自己的一个内存空间,

另外,String对象的内容一旦声明就不能轻易改变,如果想改变一个String对象的值,则第一步要做的是先将原有的String引用断开,之后再开辟新的内存空间,而且如果用new关键字开辟String对象的内存空间的话,则实际上就开辟了两个内存空间,如下所示:


从上面(A)中不难发现,String对象一旦声明则不能轻易改变,如果要改变则需要先断开原有的对象引用,再开辟新的对象,之后再指向新的对象空间。

(B)的方法也可以实现改变String对象的声明的操作,可以发现,用new String("java")方式实例化String对象时,实际上是开辟了两个内存空间,所以一般在开发商都采用直接赋值的方式,即: String str1 = "java" 。


static静态变量:

范例:TestStaticDemo1.java
01 class Person
02 {
03 String name ;
04 String city ;
05 int age ;
06 public Person(String name, String city, int age)
07 {
08 this.name = name ;
09 this.city = city ;
10 this.age = age ;
11 }
12 public String talk()
13 {
14 return "我是:"+this.name+",今年:"+this.age+"岁,来自:"+this.city;

15 }
16 }
17 public class TestStaticDemo1
18 {
19 public static void main(String[] args)
20 {
21 Person p1 = new Person("张三",25,"中国") ;
22 Person p2 = new Person("李四",30,"中国") ;
23 Person p3 = new Person("王五",35,"中国") ;
24 System.out.println(p1.talk()) ;
25 System.out.println(p2.talk()) ;
26 System.out.println(p3.talk()) ;
27 }
28 }

由上面的程序可以发现,所有的Person对象都有一个city属性,而且所有的属性也全部相同,如下所示:


读者可以试着想一想,现在假设程序产生了50个Person对象,如果想修改所有人的city属性的话,是不是就要调用50遍city属性,进行重新修改,显然太麻烦了。所以在java中提供了static关键字,用它来修饰类的属性后,则此属性就是公共属性了。将TestStaticDemo1.java程序稍作修改就形成了范例TestStaticDemo2.java

范例:TestStaticDemo2.java
01 class Person
02 {
03 String name ;
04 static String city = "中国";
05 int age ;
06 public Person(String name,int age)
07 {
08 this.name = name ;
09 this.age = age ;
10 }
11 public String talk()
12 {
13 return "我是:"+this.name+",今年:"+this.age+"岁,来自:"+city;

14 }
15 }
16 public class TestStaticDemo2
17 {
18 public static void main(String[] args)
19 {
20 Person p1 = new Person("张三",25) ;
21 Person p2 = new Person("李四",30) ;
22 Person p3 = new Person("王五",35) ;
23 System.out.println("修改之前信息:"+p1.talk()) ;
24 System.out.println("修改之前信息:"+p2.talk()) ;
25 System.out.println("修改之前信息:"+p3.talk()) ;
26 System.out.println(" ************* 修改之后信息 **************");
27 // 修改后的信息
28 p1.city = "美国" ;
29 System.out.println("修改之后信息:"+p1.talk()) ;
30 System.out.println("修改之后信息:"+p2.talk()) ;
31 System.out.println("修改之后信息:"+p3.talk()) ;
32 }
33 }

程序只在第28行修改了city属性,而且只修改了一个对象的city属性,但再次输出时,发现全部的对象的city值都发生了一样的变化,这就说明了用static声明的属性是所有对象共享的


所有的对象都指向同一个city属性,只要当中有一个对象修改了city属性的内容,则所有对象都会被同时修改

另外,读者也需要注意一点,用static方式声明的属性,也可以用类名直接访问,拿上面的程序来说,如果想修改city属性中的内容,可以用如下方式:
Person.city = “美国” ;


注意:

既然static类型的变量是所有对象共享的内存空间,也就是说无论最终有多少个对象产生,也都只有一个static类型的属性,那可不可以用它来计算类到底产生了多少个实例对象呢?读者可以想一想,只要一个类产生一个新的实例对象,都会去调用构造方法,所以可以在构造方法中加入一些记数操作,如下面的程序:

class Person
{
static int count = 0 ; // 声明一static类型的整型变量
public Person()
{
count++ ; // 增加了一个对象
System.out.println("产生了:"+count+"个对象!");
}
}
public class TestStaticDemo3
{
public static void main(String[] args)
{
new Person() ;
new Person() ;
}
}


理解main方法:

如果一个类要被Java解释器直接装载运行,这个类中必须有main()方法。

由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。

向java中传递参数可用如下的命令:
java 类名称参数1 参数2 参数3


public class TestMain
{
 /*
 public:表示公共方法
 static:表示此方法为一静态方法,可以由类名直接调用
 void:表示此方法无返回值
 main:系统定义的方法名称
 String args[]:接收运行时参数
 */
	public static void main(String[] args)
	{
	 // 取得输入参数的长度
		int j = args.length ;
		if(j!=2)
		{
			System.out.println("输入参数个数有错误!") ;
			// 退出程序
			System.exit(1) ;
		}
		for (int i=0;i<args.length ;i++ )
		{
			System.out.println(args[i]) ;
		}
	}
}

静态代码块

一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行,且只执行一次,静态代码块经常用来进行类属性的初始化。如下面的程序代码所示:

class Person
{
	public Person()
	{
		 System.out.println("1.public Person()");
	}
	 // 此段代码会首先被执行
	static
	{
		System.out.println("2.Person类的静态代码块被调用!");
	}
}

public class TestStaticDemo5 {
	// 运行本程序时,静态代码块会被自动执行
	static
	{
		System.out.println("3.TestStaticDemo5类的静态代码块被调用!");
	}
	
	public static void main(String[] args) {
		System.out.println("4.程序开始执行!");
		// 产生两个实例化对象
		new Person() ;
		new Person() ;
	}
}
从程序运行结果中可以发现,放在TestStaticDemo5类中的静态代码块首先被调用,这是因为程序首先执行TestStaticDemo5类,所以此程序的静态代码块会首先被执行。程序在22、23行产生了两个匿名对象,可以发现Person类中的静态代码块只执行了一次,而且静态代码块优先于静态方法,由此可以发现,静态代码块可以为静态属性初始化。

对象数组的使用


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值