您的位置:首页 > 其它

成员变量和局部变量的区别、方法的形参为类的情况及匿名对象、封装(private关键字)、this关键字、构造方法、static关键字

2017-04-24 18:31 746 查看
成员变量和局部变量

在介绍类的时候,已经说到了类的成员变量

成员变量是在类中而在方法之外

class ss{
int age;

}

局部变量是在方法定义中或者方法声明中

class ss{
public void call(String name){
String name2;
}

}

成员变量是随着对象存在的,对象创建而存在,随着对象消失而消失

成员变量存储在堆内存中,局部变量存储在栈内存中

堆中的变量有初始化默认值即创建了类的对象之后随即变量会有默认初始值,栈中没有。

当局部变量和成员变量相同的时候,java中会采用就近原则选择就近的变量。

class S{
int age;
public void m(){
int age;
System.out.println(age);//输出的是局部变量age
}

}

方法的形式参数是引用数据类型(类)

匿名对象,即没有名字的对象的使用

先介绍有名字的情况:

Student s = new Student();

匿名的情况:

new Student().show();这里没有将new出来的对象赋值给变量就是匿名对象,调用了方法show()

使用场景:对象的方法仅仅需要调用一次的时候;作为参数传递

匿名对象的好处:调用完成之后就成了垃圾,等待垃圾回收器回收!注意所谓垃圾就是指的没有变量

指向的废弃的对象,而Student s=new Student()这种情况,是有一个变量s指向它的。

封装:

从一个例子开始:

class Student{
int age;

}

Student s = new Student();

s.age = -15;

这个学生的年龄显然是不合理,那么现在我们需要对成员变量进行一个数据校验

class Student{
int age;
public void setAge(int age){
if(age<0){
System.out.println("给的年龄有问题");
}else{
this.age = age;
}
}

}

改进后我们添加了一个设置成员变量的方法,并加赋值之前进行数据校验

所以我们可以这样赋值

Student.s = new Student();

s.setAge(-22);//提示给的年龄有问题

但是还是有一个问题,虽然增加了这个方法,但是我们在实际使用的时候仍然可以直接对

成员变量进行赋值而跳过数据校验,所以还需进一步改进

class Student{
private int age;
public void setAge(int age){
if(age<0){
System.out.println("给的年龄有问题");
}else{
this.age = age;
}
}

}

与上次的代码相比,这里将成员变量前面增加了个private修饰符,这样这个成员变量就成为

了私有的成员变量,只能通过我们提供的方法访问。

这个就是封装的概念:

封装概述

是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

隐藏实现细节,提供公共的访问方式

提高了代码的复用性

提高安全性。

封装原则:

将不需要对外提供的内容都隐藏起来。

把属性隐藏,提供公共方法对其访问。

private关键字:

是一个权限修饰符。

可以修饰成员(成员变量和成员方法)

被private修饰的成员只在本类中才能访问。

被private修饰的成员方法和成员变量一样,不能直接

class Student{
private int age;
public void setAge(int age){
if(age<0){
System.out.printl
cef3
n("给的年龄有问题");
}else{
this.age = age;
}
}

private void show(){
System.out.println("年龄"+this.age);
}

public void function(){
show();
}

}

new Student().show();//这样是不可以的!

new Student().function();//这样是可以的,通过公共方法间接地访问私有方法

this关键字:

在前面的示例代码中我已经使用了this关键字,这里还是说明一下

如果不用this
public void setAge(int age){
if(age<0){
System.out.println("给的年龄有问题");
}else{
age = age;  //注意这里将this去掉了
}
}

那么这段赋值方法将无效了,因为根据之前说过的,当在类中出现2个同名变量的时候,取

就近原则,那么这2个age变量都是指的参数传递过来的age变量,是同一个变量!所以不会将值赋给

类的成员变量。

在给成员变量赋值的时候,只能通过对象进行赋值!

于是java提供了一个this关键字,指代当前对象的引用,所谓当前对象就是指谁调用这个

方法,this就指的是谁!比如

Student s= new Student();

s.setAge(24);

这里创建了个Student类的对象,然后调用这个对象的show方法,如果这个时候show方法中

有this关键字,那么this指的就是s指向的这个对象,所以在方法中使用this.age=age;表示将

参数值赋值给s这个对象的age成员变量。

构造方法:

对对象进行初始化的方法

格式:

1.方法名与类名相同

2.没有返回值类型,连void都没有

在前面所有的示例代码中,虽然我们没有明确写上构造方法,这样子系统会默认提供一个空的无参构造方法

比如

public Student(){};一个空的方法

但是如果我们自己写了一个无参的构造方法,系统将不再提供

注意:

只要自己已经写了构造方法,不管是带参还是不带参的,系统都不将提供构造方法

类的初始化过程

class Student{
private String name = "张三";//这种写法叫做显示初始化,是可以这样写,但是显示世界肯定是不建议这样写的
private int age = 27;

Student (String name,int age){//public关键字可以不写,系统默认情况下就是带public关键字的
this.name = name;
this.age = age;
}

public static void main(String[] args){
Student s = new Student();
System.out.println(s.getName());
}

}

执行new Student()后的运行过程:

1.加载.class文件,并将main加载进入栈

2.在栈内存给s开辟一个空间

3.在堆中为学生对象申请一个空间,并给成员变量进行”默认“初始化(0,null等)

4.给成员变量进行显示初始化

5.通过构造方法对成员变量进行初始化

6.将初始化完毕的对象在堆内存中地址值赋值给栈内存的s变量

用一个例子来熟悉下创建个标准的对象:

/*
需求:
定义一个员工类,自己分析出几个成员
然后给成员变量,构造方法,getXxx()/setXxx()方法
以及一个现实所有成员信息的方法。并测试

*/

class Employee{
//编号
private String empId;
//姓名
private String name;
//年龄
private int age;
 
//构造方法
public Employee(){}

//获取成员变量的get方法
public String getEmpId(){
return empId;
}

public String getName(){
return name;
}

public int getAge(){
return age;
}

//设置成员的set方法
public void setEmpId(String empId){
this.empId = empId;
}

public void setName(String name){
this.name = name;
}

public void setAge(int age){
this.age = age;
}

//显示方法
public void show(){
System.out.println(empId+"---"+name+"---"+age);
}
//main方法也可以写在这里作为程序的入口,并非一定要单独写个类

public static void main(String[] args){
Employee e = new Employee();

e.setEmpId("龙哥手下:9527");
e.setAge(27);
e.setName("唐伯虎");

e.show();
}

}

static关键字/静态修饰符:

还是从一个例子开始,以上面的员工类为基础,增加一个“国籍”属性

class Employee{
//编号
private String empId;
//姓名
private String name;
//年龄
private int age;
//国籍
static String country;

public void setCountry(String country){
this.country = country;
}

//显示方法
public void show(){
System.out.println(empId+"---"+name+"---"+age+"---"+country);
}
...

}

public static void main(String[] args){
Employee e1 = new Employee()
e1.setName("张三");
e1.setCountry("中国");
e1.show();

Employee e2 = new Employee()
e2.setName("李四");
e2.show();

}

在创建第二个员工对象并进行赋值的时候,我们并没有给其赋值国籍,但是输出的时候

会发现第二个员工对象仍然有国籍属性,而且和第一个员工对象的一致,这就是由于国籍属性加上了

static关键字的缘故,被static修饰的变量是所有对象共享的

static关键字的特点:

可以修饰成员变量和成员方法

static关键字特点

随着类的加载而加载

优先于对象存在

被类的所有对象共享

这也是我们判断是否使用静态关键字的条件

可以通过类名调用,也可以通过对象名调用

static关键字注意事项

在静态方法中是没有this关键字的

静态方法只能访问静态的成员变量和静态的成员方法

使用static修饰的变量叫做类变量,使用static修饰的方法叫做类方法,即为可以通过类进行调用的

变量和方法。

之前提到过内存中有个方法区的概念,其实方法区中还有个专门的静态区

使用静态修饰符修饰的东西,随着类的加载而加载,而且优先于对象存在,

这也就意味我们不需要新建对象,就可以使用类的类方法和类成员了(前提不要用

private进行修饰)

静态方法不能访问非静态的变量和非静态的方法

比如如果我们在Employee类中建立一个static方法

public static void show2(){
System.out.println(name);

}

这样将会报错,提示无法从静态上下文中引用非静态变量

class Teacher{
public int num = 10;
public static int num2 = 20;

public void show(){
System.out.println(num);
}

//静态方法只能访问静态变量和静态方法
public static void method(){
//无法从静态上下午获取非静态变量
//System.out.println(num);
//静态变量可以访问
System.out.println(num2);
}
//非静态的方法既可以访问静态变量又可以访问非静态变量
public void show(){
System.out.println(num);
System.out.println(num2);
}

}

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

}

}

关于静态方法main

public static void main(String[] args) {}

public 被jvm调用,访问权限足够大。

static 被jvm调用,不用创建对象,直接类名访问

void被jvm调用,不需要给jvm返回值

main 一个通用的名称,虽然不是关键字,但是被jvm识别

String[] args 以前用于接收键盘录入的,早期是这么用的,但是现在有了Scanner输入

所以就不用了。

args的演示案例

在控制台输入
java TeacherDemo hello world java即可输出args的内容,args即表示hello world java

补充一点:

构造方法后面可否加上return呢?

答案是可以的!但是只能写成这种 return;

不能带具体的返回值,因为其实return;仅仅只是表示一个方法的结束,包括像返回值为

void的普通方法也可以在最后加上一个return;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐