文章目录
1. this关键字
this关键字主要有三个方面的用途:
- this表示本类属性。
- this表示本类方法。
- this表示当前对象。
1.1 this表示本类属性
观察以下代码:
class Person{
private String name;
private int age;
//构造函数
public Person(String name,int age)
{
name=name;
age=age;
}
public void work()
{
System.out.println(name+"在工作!");
}
public void age()
{
System.out.println(name+age+"岁了!");
}
}
public class Test{
public static void main(String[] args)
{
Person per1=new Person("花花",-18);
per1.work();
per1.age();
}
}
执行结果:
null在工作!
null0岁了!
通过以上代码,我们发现当参数与类中的属性同名时,类中的属性无法被正确赋值(根据就近使用原则,相当于自己=自己)。此时我们加上this关键字便可以正确给对象属性赋值。
class Person{
private String name;
private int age;
//构造函数
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public void work()
{
System.out.println(name+"在工作!");
}
public void age()
{
System.out.println(name+age+"岁了!");
}
}
public class Test{
public static void main(String[] args)
{
Person per1=new Person("花花",18);
per1.work();
per1.age();
}
}
所以只要在类中访问类的属性,一定要加上this关键字
1.2 this调用本类方法
1.2.1 this调用普通方法
格式:this.方法名称(参数)
class Person{
private String name;
private int age;
//构造函数
public Person(String name,int age)
{
this.name=name;
this.age=age;
this.work();
}
public void work()
{
System.out.println(name+"在工作!");
}
public void age()
{
System.out.println(name+age+"岁了!");
}
}
public class Test{
public static void main(String[] args)
{
Person per1=new Person("花花",18);
}
}
虽然调用本类的普通方法不需要加this也可以正常调用,但还是建议加上,在继承关系中,this的可以区分方法定义来源
1.2.2 this调用构造方法
观察构造方法存在的问题:
class Person{
private String name;
private int age;
public Person(){
System.out.println("********产生一个新的Person对象********");
}
public Person(String name){
System.out.println("********产生一个新的Person对象********");
this.name = name ;
}
public Person(String name,int age){
System.out.println("********产生一个新的Person对象********");
this.name = name ;
this.age = age ;
}
public String getPersonInfo(){
return "姓名:" + name + ",年龄:"+age;
}
}
public class Test{
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person("张三");
Person per3 = new Person("李四",20);
System.out.println(per1.getPersonInfo());
System.out.println(per2.getPersonInfo());
System.out.println(per3.getPersonInfo());
}
}
执行结果:
******** 产生一个新的Person对象********
******** 产生一个新的Person对象********
******** 产生一个新的Person对象********
姓名:null,年龄:0
姓名:张三,年龄:0
姓名:李四,年龄:20
上述代码编译执行没有问题,但有大量的重复代码,在java中不允许有重复代码的出现。那怎么解决呢?
在Java中,支持构造方法的互相调用。
修改上述代码:
class Person{
private String name;
private int age;
public Person(){
System.out.println("********产生一个新的Person对象********");
}
public Person(String name){
this(); //调用本类无参构造
this.name = name ;
}
public Person(String name,int age){
this(name); //调用本类有参构造
this.age = age ;
}
public String getPersonInfo(){
return "姓名:" + name + ",年龄:"+age;
}
}
public class Test{
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person("张三");
Person per3 = new Person("李四",20);
System.out.println(per1.getPersonInfo());
System.out.println(per2.getPersonInfo());
System.out.println(per3.getPersonInfo());
}
}
执行结果:
******** 产生一个新的Person对象********
******** 产生一个新的Person对象********
******** 产生一个新的Person对象********
姓名:null,年龄:0
姓名:张三,年龄:0
姓名:李四,年龄:20
使用this调用构造方法时请注意:
- this调用构造方法的语句必须在构造方法的首行。
- this调用构造方法不允许成环。
1.2.3 this表示当前对象
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age ;
}
public void getPersonInfo(){
System.out.println(this +" 姓名:" + name + ",年龄:"+age);
}
}
public class Test{
public static void main(String[] args) {
Person per1 = new Person("李四",17);
System.out.println("&per1="+per1);
per1.getPersonInfo();
Person per2 = new Person("张三",18);
System.out.println("&per2="+per2);
per2.getPersonInfo();
}
}
2. static关键字
2.1 static修饰属性
观察此段代码:
class Person{
private String name;
private int age;
private String schoolName;
//构造方法
public Person(String name, int age, String schoolName)
{
this.name=name;
this.age=age;
this.schoolName=schoolName;
}
public void getPeopleInfo()
{
System.out.println("学校:"+schoolName+" 姓名:"+name+" 年龄:"+age);
}
}
public class Test{
public static void main(String[] args) {
Person per1=new Person("张三",18,"励志中学");
Person per2=new Person("李四",17,"励志中学");
per1.getPeopleInfo();
per2.getPeopleInfo();
}
}
内存分析图:
一个学校里有成千上万个学生,虽然名字各不相同,但是学校名称却是相同的,像上图那样保存学生的信息,会造成系统资源的大量浪费。
若想要描述共享属性,只需在属性前添加static关键字即可。
修改上述代码:public static String schoolName=“励志中学”; //static之前必须用public修饰
class Person{
private String name;
private int age;
public static String schoolName="励志中学";
public Person(String name, int age)
{
this.name=name;
this.age=age;
}
public void getPeopleInfo()
{
System.out.println("学校:"+schoolName+" 姓名:"+name+" 年龄:"+age);
}
}
public class Test{
public static void main(String[] args) {
Person per1=new Person("张三",18);
Person per2=new Person("李四",17);
per1.getPeopleInfo();
per2.getPeopleInfo();
System.out.println(Person.schoolName);
}
}
此时的内存分析图如下:
static修饰的属性称为类属性,保存在全局数据区中(方法区-所有对象的共享区域),通过类名调用,与对象实例化无关。
类属性是在类加载的时候初始化,而且只被初始化一次。在程序中任何对象对静态变量做修改其他对象看到的是修改后的值。
结论:
- 访问static属性(类属性)应使用 类名称.属性名
- 所有的非static属性必须在对象实例化后使用,而static属性(类属性)不受对象实例化的控制。
2.2 static修饰方法
通过类名调用,与对象实例化无关,常用于工具类方法。
典型的静态方法:
i.Arrays.sort(数组名称) 数组排序
ii.System.arraycopy(源数组名称,源数组开始点,目标数组名称,目标数组开始点,拷贝个数) 数组拷贝
iii.Arrays.copyOf(源数组名称,目标数组长度) 数组全拷贝
class Person{
private String name;
private int age;
public static String schoolName;
public Person(String name, int age)
{
this.name=name;
this.age=age;
}
//静态方法
public static void setschoolName(String n)
{
schoolName=n;
}
public void getPeopleInfo()
{
System.out.println("学校:"+schoolName+" 姓名:"+name+" 年龄:"+age);
}
}
public class Test{
public static void main(String[] args) {
//直接通过类名调用与对象无关
Person.setschoolName("励志中学");
Person per1=new Person("张三",18);
Person per2=new Person("李四",17);
per1.getPeopleInfo();
per2.getPeopleInfo();
}
}
关于static方法的说明:
- static修饰的方法允许调用任何static修饰的属性或方法,但是不能调用非static修饰的属性或方法
- 局部变量(方法中的变量)不能用static修饰
- static方法就是没有this的方法,静态方法不依赖于任何对象就可以进行访问,它不依赖于任何对象,就谈不上this了
2.2 static修饰代码块
static关键字修饰的代码块叫做 静态代码块
根据静态代码块位置的不同又分为:主类中的静态代码块和非主类中的静态代码块
2.2.1 非主类中的静态代码块
class Person{
public Person(){
//构造方法
System.out.println("Person 类的构造方法");
}
{
//构造块
System.out.println("Person 类的构造块");
}
static {
//静态块
System.out.println("Person 类的静态代码块");
}
}
public class Test{
public static void main(String[] args)
{
new Person();
new Person();
}
}
由此可见,非主类中的静态代码块优先于构造块执行(构造块是不加任何修饰符的代码块,优先于构造方法执行,产生几个对象,就执行几次构造方法),且无论产生多少对象,静态代码块只执行一次。
2.2.2 主类中的静态代码块
public class Test{
public Test()
{
//构造方法
System.out.println("主类的构造方法");
}
{
//构造块
System.out.println("主类的构造块");
}
static {
//静态块
System.out.println("主类的静态代码块");
}
public static void main(String[] args)
{
System.out.println("start....");
new Test();
new Test();
System.out.println("end.....");
}
}
由此可见,主类中的静态代码块优先于主方法执行,即JVM一启动便执行。