类与对象

概念贴士:

1.  类必须先定义了才能使用。类是创建对象的模板,创建对象也叫类的实例化。

2.  在Java中,使用new关键字来创建对象,一般有一下3个步骤:

    1)声   明:声明一个对象,包括对象名称和对象类型。

    2)实例化:使用关键字new创建一个对象。

    3)初始化:使用new创建对象时,会调用构造方法初始化对象。

3.  在类实例化的过程中自动执行的方法叫做构造方法,它不需要手动调用。构造方法可以在类实例化的过程中完成一些初始化的工作。构造方法的名称必须与类的名称相同,并且没有返回值。每个类都有构造方法,如果没有显式地为类定义构造方法,Java编译器将会为该类提供一个默认的构造方法。

4.  Java通过修饰符来控制类、属性和方法的访问权限和其他功能,通常放在语句的最前端。

5.  Java的修饰符很多,分为访问修饰符和非访问修饰符。其中访问修饰符也叫访问控制符,是指能够控制类、成员变量、方法的使用权限的关键字。  在面向对象编程中,访问控制符是一个很重要的概念,可以使用它来保护对类、变量、方法和控制方法的访问。

6.  Java支持4种不同的访问权限:

    1)public      共有的,对所有类可见

    2)protected    受保护的,对同一包内的类和所有子类可见

    3)private      私有的,在同一类内可见

    4)默认的      在同一包内可见,默认不使用任何修饰符

6.1  public:公有的

    被声明为public的类、方法、构造方法行业接口能够被任何其他类访问。如果几个相互访问的public类分布在不同的包中,则需要导入相应public类所在的包。由于类的继承性,类所有的公有方法和变量都能被子类继承。

    例子:public static void main(String[] arguments){}

    PS:Java程序main()方法必须是设置成公有的。

6.2  protected:受保护的

    被声明为protected的变量、方法和构造方法能够被同一包中的任意其他类访问,也能够被不同包中的子类访问。protected访问修饰符不能修饰类和接口,方法和成员变量能够声明为protected,但是接口的成员变量和成员方法不能声明为protected。子类能访问protected修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。

    例子:

 public class Dog{
protected void bark(){
System.out.println("汪汪,不要过来!");
}
} class Teddy extends Dog{ //泰迪
protected void bark(){
System.out.println("汪汪,我好怕,不要跟着我!");
}
}

    PS:如果把bark()方法声明为private,那么除了Dog之外的类将不能访问该方法。如果把bark()方法声明为public,那么所有的类都能够访问该方法。如果只想让该方法对其所在类的子类可见,则将该方法声明为protected即可。

6.3  private:私有的

    私有访问修饰符是最严格的访问控制级别,所以被声明为private的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为private。  声明为私有访问类型的变量只能通过类中公共的getter/setter方法被外部类访问。private访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。

    例子:

 public class Dog{
private String name;
private int age;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age=age;
}
}

    PS:程序中,Dog类中的name、age变量为私有变量,所以其他类不能直接得到和设置该变量的值。为了使其他类能够操作该变量,程序中定义了两对public方法,getName()/setName()和getAge()/setAge(),用来获取和设置私有变量的值。

    PS:this是Java中的一个关键字,在类中定义访问私有变量的方法,习惯上是这样命名的:在变量名称前面添加get或者set,并将变量的首字母大写。上述两对方法由于经常使用,也有特定的称呼,称为getter和setter方法。

6.4  默认的:不使用任何关键字

    不适用任何修饰符声明的属性和方法,对同一个包内的类是常见的。接口的变量都隐式声明为public static final(final为非访问修饰符之一),而接口里的方法默认情况下访问权限为public。

6.5  访问控制符使用小总结:

  1. 访问控制符可以令我们便于控制代码的权限。

    1)当需要让自己编写的类被所有的其他类访问时,就可以将类的访问控制符声明为public。

    2)当需要让自己的类只能被自己的包中的类访问时,就可以省略访问控制符。

    3)当需要控制一个类中的成员数据时,可以将这个类中的成员数据访问控制符设置为public、protected或者省略。

  2.  方法继承的规则。

    1)父类中声明为public的方法在子类中也必须为public。

    2)父类中声明为protected的方法在子类中要么声明为protected,要么声明为public,不能声明为private。

    3)父类中默认修饰符声明的方法,能够在子类中声明为private。

    4)父类中声明为private的方法,不能被继承。

7.  在Java中,变量的作用域分为4个级别,即类级、对象实例级、方法级和块级。(详见实例3-4)

    1)类级变量又称为全局级变量或者静态变量,需要使用static关键字修饰,类级变量在类定义后就已经存在,占用内存空间,可以通过类名来访问,不需要实例化。

    2)对象实例级变量就是成员变量,实例化后才会分配内存空间,才能访问。

    3)方法级变量是在方法内部定义的变量,是局部变量。

    4)块级变量是定义在一个块内部的变量,变量的生存周期就是这个块,出了这个块则变量消失,如if、for语句的块。块是指由大括号(花括号)包围的代码。

8.  在Java中,this可以在类里引用这个类的属性和方法。this关键字用来表示当前对象本身,或当前类的一个实例,通过this关键字可以调用本对象的所有方法和属性。(详见实例3-5)

9.  成员变量与方法内部的变量重名时,希望在方法内部调用成员变量,可以通过使用this关键字区分同名变量。(详见实例3-6)

10.  在构造函数中通过this引用来调用另一个构造函数,也就是相当于调用本类的其他构造方法,它必须作为构造方法的第一句(即作为方法名初始化对象)。(详见实例3-7)

11.  需要在某些完全分离的类中调用一个方法,并将当前对象的一个引用作为参数传递时,可以使用this关键字,作为参数传递。(详见实例3-8)

12.  在Java中

,同一个类中的多个方法可以有相同的名字,但参数列表不同,这被称为方法重载(method overloading)。重载是面向对象的一个基本特性。  参数列表又叫参数签名,包括参数的类型,参数的个数与参数的顺序,只要有一个不同就叫做参数列表不同。(详见实例3-9)

13.  1.重载说明:

    1)参数列表不同包括:个数不同、类型不同和顺序不同。

    2)仅参数变量名称不同是不可以的(毕竟那只是形参)。

    3)与成员方法一样,构造方法也可以重载。

    4)声明为final的方法不能被重载(感兴趣可以查询final这个非访问修饰符)。

    5)声明为static的方法不能被重载,但是能够被再次声明。

    2.方法的重载规则:

    1)方法名称必须相同。

    2)参数列表必须不同。

    3)方法的返回类型可以不同,也可以相同。

    4)仅仅返回类型不同不足以成为方法的重载。

    3.方法重载的实现:方法名称相同时,编译器会根据调用方法的参数个数、参数类型等逐个去匹配,以选择对应的方法,如果匹配失败,则编译器报错,这叫重载分辨。

14.  Java为每种基本数据类型分别设计了对应的类,实现数据间类型转化,这些类被称之为包装类(Wrapper Classes)。

15.  封装就是将属性私有化,提供公有的方法访问私有的属性。其实现步骤如下:

    1)修改属性的可见性限制对属性的访问。

    2)为每个属性创建一对赋值方法和取值方法,用于对这些属性的访问。

    3)在赋值和取值方法中,加入对属性的存取限制。

16.  为了实现良好的封装性,通常将类的成员变量声明为private,再通过public的方法对这个变量进行访问。对一个变量的操作,一般是读取和赋值操作,下面分别定义两个方法来实现这两种操作,一个是getXxx()方法(Xxx表示要访问的成员变量的名字),用来读取这个成员变量操作;另外一个是setXxx()方法,用来对这个成员变量赋值。(详见实例3-10)

代码解释:

实例3-1

 package duke.example.ch3;

 public class Dog{
String name; //名字
int age; //年龄 void bark(){ //汪汪叫
System.out println("汪汪,不要过来");
} void hungry(){ //饥饿
System.out.println("主任,我饿了");
}
}

代码说明: 代码行.3中 public是类的修饰符,表明该类是公共类,可以被其他类访问。class是定义类的关键字,Dog是类名称。

      代码行.4-5中 name、age是类的成员变量,也叫属性。

      代码行.7-9中 bark()是类中的函数,也叫方法,即定义犬吠这个方法。

      代码行.11-13中 hungry()是类中的函数,也叫方法。

PS:一个类的变量可以包含以下类型变量。

  • 局部变量:在方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在这个方法中,方法结束后,变量就会自动销毁。
  • 成员变量:在类中、方法体之外定义的变量。这种变量在创建变量的时候实例化(分配内存)。成员变量可以被类中的方法和特定类的语句访问。
  • 类 变 量 :也是在类中、方法体之外定义的变量,但必须声明为static类型。static也是修饰符的一种。

实例3-2

 package duke.example.ch3;

 public class Dog{
String name; //名字
int age; //年龄 Dog(String name,int age){ //构造方法,没有返回值
this.name=name;
this.age=age;
System.out.println(name+“感谢主人天天带我玩耍!”);
} void bark(){ //汪汪叫
System.out println("汪汪,不要过来");
} void hungry(){ //饥饿
System.out.println("主任,我饿了");
} public static void main(String[] args){
//创建对象时传递的参数要与构造方法参数列表对应
Dog myDog=new Dog("卡拉",3);
System.out.println("我是一只小狗,我的名字叫"+name+",我"+age+"岁了!");
}
}

输出结果:

        卡拉感谢主人天天带我玩耍!
我是一只小狗,我的名字叫卡拉,我3岁了!

代码说明: 代码行.7-9中 定义包含两个参数name和age的构造函数,构造方法的名称必须与类的名称Dog相同。构造方法不能有返回值,因为没有变量来接收返回值。

      代码行.23中 构造方法不能被显示调用,在类Dog实例化的过程中自动执行了。

代码执行顺序:

  1)先运行到代码行.21。这是程序的入口。

  2)然后运行代码行.23。这里要创建一个Dog,就要调用Dog的构造方法。

  3)运行到代码行.7。注意接下来并不是运行代码行.8,初始化一个类,必须先初始化他的属性。

  4)因此运行到代码行.4。然后是代码行.5。

  5)属性初始化后,才回到构造方法,执行里面的代码,也就是代码行.8-10。

  6)然后是代码行.11。表示创建一个Dog实例完成。

  7)然后回到main()方法中执行代码行.23-24。

  8)最后是代码行.25。main()方法执行完毕。

书上说作为程序员,应该知道程序的基本运行过程,否则不利于编写代码与进步,其实这是有道理的。在一个程序中,你看到的深度决定了你编程水平的上限。

实例3-3

 package duke.example.ch3;

 public class Dog{
String name; //名字
int age; //年龄 Dog(String name,int age){ //构造方法,没有返回值
this.name=name;
this.age=age;
System.out.println(name+“感谢主人天天带我玩耍!”);
} void bark(){ //汪汪叫
System.out println("汪汪,不要过来");
} void hungry(){ //饥饿
System.out.println("主任,我饿了");
} public static void main(String[] args){
//创建对象时传递的参数要与构造方法参数列表对应
Dog myDog=new Dog("卡拉",3);
//访问成员变量
String name=myDog.name;
int age=myDog.age;
System.out.println("我是一只小狗,我的名字叫"+name+",我"+age+"岁了!");
//访问方法
myDog.bark();
myDog.hungry();
}
}

输出结果:

        卡拉感谢主人天天带我玩耍!
我是一只小狗,我的名字叫卡拉,我3岁了!
汪汪,不要过来!
主人,我饿了!

代码说明: 代码行.26-27中 通过点号(.)访问变量name和age。

      代码行.29-30中 通过点号(.)访问成员方法bark()和hungry()。

实例3-4

 package duke.example.ch3;

 public class Scope{
public static String name="爪哇岛旅游攻略"; //类级变量
public int i; //对象实例级变量 //属性块,在类初始化属性时候运行
{
int j=2; //块级变量
} public void test(){
int j=3; //方法级变量
if(j==3){
int k=5;
}
//这里不能访问块级变量,块级变量只能在块内部访问
System.out.println("name="+name+",i="+i+",j="+j);
} public static void main(String[] args){
//不创建对象,直接通过类名访问类级变量
System.out.println(Scope.name);
//创建对象并访问它的方法
Scope.scope=new Scope();
scope.test();
}
}

输出结果:

        爪哇岛旅游攻略
name=爪哇岛旅游攻略,i=0,j=3

代码说明: 代码行.4中 使用static关键字定义类级字符串变量name。

      代码行.12-19中 定义方法test(),方法内部定义了方法级变量和块级变量。

PS:  1)方法内部除了能访问方法级的变量,还可以访问类级和实例级的变量。

     2)块内部能够访问类级、实例级变量,如果块被包含在方法内部,它还可以访问方法级的变量。

     3)方法级和块级的变量必须被显式初始化,否则不能访问。

 实例3-5

 package duke.example.ch3

 public class ThisDemo1 {
public int x=10;
public int y=15; public void sum() {
int z=this.x+this.y;
System.out.println("x+y="+z);
} public static void main(String[] args) {
ThisDemo1 thisdemol=new ThisDemo1();
thisdemo1.sum();
}
}

输出结果:

        x+y=

代码说明: 代码行.4-5中 定义成员变量x和y。

      代码行.8中 通过this点取成员变量。

PS:上面程序中,thisdemol时ThisDemol类的一个实例,this和thisdemol等价,执行int z=this.x+this.y;,就相当于执行int z=thisdemol.x+thisdemol.y;。

PS:this只有在类实例化后才有意义。

实例3-6

 package duke.example.ch3;

 public class ThisDemo2 {
public String name;
public int age; public ThisDemo2(String name,int age) {
this.name=name;
this.age=age;
} public void say() {
System.out.println("网站的名字是"+name+",已经成立了"+age+"年");
} public static void main(String[] args) {
ThisDemo2 thisdemo2=new ThisDemo2("www.baidu.com",15);
thisdemo2.say();
}
}

输出结果:

        网站的名字是www.baidu.com,已经成立了15年

代码说明: 代码行.7-10中 成员变量与方法内部的变量重名时,通过this引用调用成员变量。  形参的作用域是整个方法体,是局部变量。在ThisDemo2(String name,int age)中,形参与成员变量重名,如果不使用this,访问到的就是局部变量name和age,而不是成员变量。

      代码行.12-14中 在say()中没有使用this,因为成员变量的作用域是整个实例,当然也可以加上this。

        eg:System.out.println("网站的名字是"+this.name+",已经成立了"+this.age+"年"):

PS:Java默认将所有成员变量和成员方法与this关联在一起,因此使用this在某些情况下是多余的。

实例3-7

 package duke.example.ch3;

 public class ThisDemo3 {
public String name;
public int age; public ThisDemo3() {
this("www.baidu.com",15);
} public ThisDemo3(String name,int age) {
this.name=name;
this.age=age;
} public void say() {
System.out.println("网站的名字是"+name+",已经成立了"+age+"年");
} public static void main(String[] args) {
ThisDemo3 thisdemo3=new ThisDemo3();
thisdemo3.say();
}
}

输出结果:

        网站的名字是www.baidu.com,已经成立了5年

代码说明: 代码行.7-9中 在构造方法中,this调用另一个构造方法,调用动作必须置于最起始的位置。注意,不能在构造方法以外的任何方法内调用构造方法,在一个构造方法内只能调用一个构造方法。

PS:上述代码设计方法重载,即Java允许出现多个同名方法,只要参数不同即可。

实例3-8

 package duke.example.ch3;

 public class ThisDemo4 {

     public static void main(String[] args) {
B b=new B(new A());
}
} class A {
public A() {
new B(this).print();
} public void print() {
System.out.println("Hello from A!");
}
} class B {
A a; public B(A a) {
this.a=a;
} public void print() {
a.print();
System.out.println("Hello from B!");
}
}

输出结果:

        Hello from A!
Hello from B!

代码说明: 代码行.12中 匿名对象就是没有名字的对象。如果对象只是用一次,就可以作为匿名对象,代码中new B(this).print();等价于(new B(this)).print();,先通过new B (this)创建一个没有名字的对象,再调用它的方法。

实例3-9

 package duke.example.ch3;

 public class Overload {
//一个普通的方法,不带参数的
void test() {
System.out.println("No parameters");
} //重载上面的方法,并且带了一个整型参数
void test(int a) {
System.out.println("a:"+a);
} //重载上面的方法,并且带了两个整型参数
void test(int a,int b) {
System.out.println("a and b:"+a+" "+b);
} //重载上面的方法,并且带了一个双精度参数
double test(double a) {
System.out.println("double a:"+a);
return a*a;
} public static void main(String[] args) {
Overload overload=new Overload();
overload.test;
overload.test(2);
overload.test(2,3);
overload.test(2,0);
}
}

输出结果:

        No parameters
a:2
a and b:2 3
double a:2.0

PS:重载就是在一个类中,有相同的函数名称,但形参不同的函数。重载的结果,可以让一个程序段减少代码和方法的种类。

实例3-10

 package duke.example.ch3;

 public class Person {
//封装属性:将属性设置为私有
private String name;
private int age; public String getName() { //外部通过此方法访问name属性
return name;
} public void setName(String name) { //该方法是外部赋值私有属性name
this.name=name;
} public int getAge() { //外部通过此方法访问age属性
return age;
} public void setAge(int age) { //该方法使外部赋值私有属性age
shis.age=age;
} void say() { //此方法可以被外部直接调用使用
System.out.println("我叫"+name+",今年"+age+"岁了!");
} public static void main(String[] args) {
Person person=new Person();    //实例化person类
person.setName("小芳"); //通过开放方法给实例化对象的name属性赋值
person.setAge(22); //通过开放方法给实例化对象的age属性赋值
person.say(); //通过实例化对象的方法
}
}

输出结果:

        我叫小芳,今年22岁了!

代码说明: 代码行.5-6中 private是修饰符表示私有化,这就封装了类的属性,封装后外部不能直接使用该属性。

      代码行.7-22中 对外用标准的set/get方法修改/读取属性name和age的值。

      代码行.24中 定义方法say(),该方法可以被外部直接调用使用。

PS:封装的优点:

    1)隐藏类的实现细节。

    2)让使用者只能通过实现制定好的方法访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作。

    3)便于修改,增强了代码的可维护性。

总结:这一部分主要谈到了Java的类及其相关基础应用。另外,类的继承和多态是其高阶应用。

《JAVA程序设计与实例》记录与归纳--类与对象的更多相关文章

  1. 077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象

    077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象 本文知识点:类和对象 说明:因为时间紧张,本人写博客过程中只是对知识点 ...

  2. JAVA基础语法:函数(方法)、类和对象(转载)

    4.JAVA基础语法:函数(方法).类和对象 函数 在java中函数也称为方法,是一段具备某种功能的可重用代码块. 一个函数包括这几部分: 函数头 函数头包括函数访问修饰符,函数返回值类型, 函数名, ...

  3. Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员、局部),匿名对象的调用,构造代码块(5)

    Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员.局部),匿名对象的帝爱用,构造代码块(5)

  4. 《JAVA程序设计与实例》记录与归纳--继承与多态

    继承与多态 概念贴士: 1. 继承,即是在已经存在的类的基础上再进行扩展,从而产生新的类.已经存在的类成为父类.超类和基类,而新产生的类成为子类或派生类. 2. Java继承是使用已存在的类的定义作为 ...

  5. 【Head First Java 读书笔记】(二)类与对象

    前篇当中,代码都放在main()里面,那根本不是面向对象的做法. 椅子大战(对象如何改变你的一生) 程序规格: 在图形接口画出四方形,圆形和三角形,当用户点选图形时,图形需要顺时针转360度并依据形状 ...

  6. [Java]Java入门笔记(三):类、对象和方法

    七.类.对象和方法 类和对象的关系 类定义了对象的本质: 类(class)是对象(object)的模板,而对象(object)是类的一个实例(instance). 使多个对象的指向相同: Studen ...

  7. 04737_C++程序设计_第4章_类和对象

    例4.1 描述点的Point类. 例4.2 根据上面对Point类的定义,演示使用Point类的对象. #define _SCL_SECURE_NO_WARNINGS #include <ios ...

  8. java学习笔记(三):类和对象

     创建对象 构造器 每一个类都有一个构造器. 如果我们不单独为一个类编写构造器那么 Java 的编译器将会给这个类建立一个默认的构造器. 每当一个新的对象被创建,至少一个构造器将会被调用. 构造器的一 ...

  9. 《Java入门第二季》第一章 类和对象

    什么是类和对象 如何定义 Java 中的类 如何使用 Java 中的对象 Java中的成员变量和局部变量1.成员变量:在类中定义,描述构成对象的组件. 2.局部变量:在类的方法中,用于临时保存数据. ...

随机推荐

  1. inline-block并列排序时候的影响

    当两个设置了inline-block属性的元素并列排放时,它们的位置能够互相影响. 元素结构: <div class="container"> <div clas ...

  2. Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name': was expecting ('true', 'false' or 'null')

    Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name': was expecting ( ...

  3. 使用WebEx录制视频并转换为MP4

    1.下载并安装WebEx http://www.question-defense.com/wp-content/uploads/2010/05/ateditor-version-3.0.zip 2.打 ...

  4. ASP.NET Core MVC请求超时设置解决方案

    设置请求超时解决方案 当进行数据导入时,若导入数据比较大时此时在ASP.NET Core MVC会出现502 bad gateway请求超时情况(目前对于版本1.1有效,2.0未知),此时我们需要在项 ...

  5. sqlserver 存储过程 分页搜索查询

    具体调用实例见代码最后一行注释区域 --if exists(select * from sysobjects where id = object_id(N'page_search') and type ...

  6. HTTP之URL分解

    HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接.URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息 URL,全称是U ...

  7. iOS 类似2048、4096小游戏-OC

    大概思路(初步制作,粗工制造):demo 1.Collection 创建cell 2.cell上添加一个view,用来添加手势 3.字典用来存放数据->每次执行StarGame数组接收没有数字的 ...

  8. Visual Studio Code 快捷键大全(Windows)

    Visual Studio Code 是一款优秀的编辑器,非常适合编写 TS 以及 React .最近在学习 AngularJs 2,开始使用 VSCode,特意整理翻译了一下官网的快捷键.因为已经习 ...

  9. bzoj 3575: [Hnoi2014]道路堵塞

    Description A 国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国交通部指定了一条从城市1到城市N的路径, 并且保证这条路径的长度是所 ...

  10. unity -- Time类(持续更新中)

    2018年了,新年总是会制定很多具体目标和计划,不管能否坚持去完成,初衷和决心总是要有的.本年第一篇博客终于开始下笔了,先立一些今年和公司业务无关的的flag: 1.希望每月或两月能看一套蛮牛游戏上的 ...