类与对象
这是我的第一篇博客,写博客的目的是为了能在学习的过程之中更加熟练地掌握知识点,并能够早日变成大佬(23333)
JAVA中的的类和对象和C++中的差不多,但是却应用得更加广泛,基本JAVA中所有的语句都和类与对象分不开关系。
而面向对象的编程思想(将现实世界中的事物都转化为类与对象来描述)。类即某一类事物的抽象描述,对象就是某类事物中的一个个体。(如学生这一类和某个具体的学生这一个个体)
而一个类可以定义多个对象,而类用于描述多个对象共同具有的特征。
定义一个类
class Myclass
{
int i;
}
在上面的代码中myclass是一个新定义的类,类名为myclass,无其他修饰符和继承及接口(以后会讲),类体内有一个数据成员i,类型为int。
class Point
{
private int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}
public int getx()
{
return x;
}
}
Point是一个新定义的类,类名为Point,类体内除了有私有数据成员x,y外,还有构造方法、实例方法(之后具体讲到)
创建类的对象
对象也称为实例,而JAVA中所有的类都属于引用类型(int,String,float,char等基本数据类型为值类型)想学八种基本数据类型的可以参考这个🔗
而两种数据类型的主要区别在于:值类型的变量中存储实际的值(数据),引用类型的变量存储引用,这个引用指向实际的数据(对象)。
所以创建类的对象的时候会有这样子的语句:
Point p=new Point();
现在让我们来仔细地区分一下引用变量和对象。p是引用变量,引用变量不会存储实际的数据,用于引用至一个对象,而这个对象是使用new操作符新创建的Point类的对象。这个对象在内存中分配有存储空间,这个对象才是真正的实际数据。
而上面的创建对象的代码可分为两步来解读:Point p:建立一个引用类型的变量。new Point():使用new操作符创建对象。
至于new运算符的作用:申请空间用于新对象的内存分配、调用构造方法初始化对象等。
而创建对象后的引用值由那个引用变量来接收。
下面我们来细究对象和对象引用的联系与区别:对象是由new操作符创建的,对象引用是由类定义的变量,这个变量存储着对象在内存中的引用(地址)。虽然只是一个引用,但却可以来操作这个对应对象。
public class Myclass {
public static void main(String[] args)
{
test i1=new test();
i1.i=20;
test i2=i1;
i2.i=40;
System.out.println(i1.i);//输出为40
}
}
class test
{
int i;
}
先用一个new操作符来创建一个对象,然后给i1引用,这时值为20,i2=i1这个操作让i2也指向对象,并改变i的值,所以最后值为40.
类的数据成员和方法
数据成员分为两种静态变量和实例变量,后面详细来讲区别,这里先学习如何调用及访问。
class Myclass
{
int a;
int b;
}
class Myclassapp
{
public static void main(String[] args)//主程序方法,先记着。
{
Myclass x=new Myclass();//x是一个引用变量
x.a=1;//实例变量的访问形式
x.b=-1;
System.out.println("实际变量的值为:"+x.a+" "+x.b);
//输出流对象来输出,先记着形式
}
}
下面来讲讲类的方法。JAVA所讲的类的方法也就C/C++中所说的函数。
常见的形式有:[修饰符] 返回值类型 方法名 (参数表){……}
方法调用的一般形式:类的引用变量名.方法名(实参表)
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
//实际调用的形式为q.max(x,y),其中x,y为实际参数,a,b只是形参。返回值是一个数字,为x,y较大者。
类中的方法常用于改变类中的数据变量的值。
下面举例几个常见的方法,供读者举一反三。
class Myclass
{
int x;
int y;
int getx()
{
return x;
}
int gety()
{
return y;
}
int changex(int value)
{
x=value;//通过外部传入的value值来改变数据成员x的值。
}
int changey(int value)
{
y=value;
}
}
对于类定义的时候你可以对数据成员进行初始化,使该类所有的对象在创建的时候都有初值。
由下面Point类创建的所有对象的数据成员x=0,y=10。
class Point
{
int x;//int型未初始化时值都为0,所以x=0
int y=10;//y=10
}
下面介绍一种特殊的方法:构造方法。
构造方法在创建对象时是必定调用的,用于数据成员的初始化,可以将数据成员的初始化封装起来。
常见形式:类名(参数表){语句}
class Point()
{
int x;
int y=10;
Point(int x1,int x2)
{
x=x1;
y=y1;
}
}
假如我创建对象的语句为Point p=new Point(3,3) (注意联系上面的new用法,构造方法被new调用)
那p的数据成员x是0还是3呢?y是10还是3呢?
实际结果x=3,y=3。这说明构造函数比初始化优先级更高。
如果一个类没有定义构造方法,系统会为类提供一个默认的不带参数的构造方法(与前面的方法创建联系理解)
构造方法往往还有另有一个作用:保证某些行为得以执行。如在类中写一个输出流方法来输出一段文字,只要有对象被创建,必有输出。也可加一些判断条件当符合条件时才输出,如判断初始化值是否合法。
同时构造方法可以重载。过载实际是同名的不同函数,通过传入参数的个数、类型、顺序来调用不同的方法。一般方法也可以重载。
下面我们来区分实例方法和静态方法。
在定义时,可以在方法前加一个修饰符static让这个方法变为静态方法。
调用实例方法的前提是这个实例存在,形式如下:类的引用变量.非静态方法名(参数值1,参数值2……)
我们就来讲讲静态方法的调用:
类名.静态方法名
不需要创建对象。
不过注意点是不能在静态方法中使用this和super指针。静态方法不能访问非静态方法和非静态成员变量。
下面来讲解一下this指针的作用:this是对当前实例的引用,当局部变量和数据成员同名时可以用来区分数据成员和局部变量
void setx(int x)
{
this.x=x;
}
下面是一个综合例子:
public class Myclass {
public static void main(String[] args)
{
test1 t=new test1();
t.setx(10);
t.sety(20);
test2 t2=new test2();
t2.fun(t);
System.out.print(t.x+" "+" "+t.rey());
}
}
class test1
{
int x;
int y;
void setx(int x)
{
this.x=x;
}
void sety(int y)
{
this.y=y;
}
int rex()
{
return x;
}
int rey()
{
return y;
}
}
class test2
{
void fun(test1 t)
{
t.setx(t.rex()*1000);
t.sety(t.rey()*1000);
}
}
结果居然是10000和20000。是不是很出乎意料,然而实际上确实如此。在类test2的fun(test t)方法中,参数表中的形参也指向了对象实际存在的内存地址,因而在方法内部的改变也代表了实际值的改变。这点和值传递的有点不同。
下面我们来看一下静态变量个和实例变量。
静态变量又称为类变量,一个类只能存在一个。而实例变量存在的个数与类创建的实例个数一致。而静态变量不仅可以是基本数据类型,还能够是类的对象。
可以通过类名.变量名来访问。
class t
{
static int x=0;
}
public class test
{
public static void main(String[] args)
{
t t1=new t();
t1.x++;
t t2=new t();
t2.x++;
System.out.println(t.x);
}
}
可以发现,无论是使用对象来访问、还是用类名来访问静态变量,都是对同一个存储进行的改变。同时静态变量在重新创建对象的时候都不会被重置。
下面来讲解一下全局变量、局部变量、静态变量、实例变量的具体特征:
- 局部变量必须赋初值
- 全局变量若不赋初值,则系统自动赋值为0
- 类中的实例变量的生存周期是对象的生存期
- 类中方法内部的局部变量的生存周期是方法的执行期,方法结束后自动释放内存
最后来了解一下final标识符
用final修饰的数据变量无法被更改,即只能被赋一次值,故也称最终成员变量。同时final变量必须要被初始化。
public final String str="abc";//例子
由于final变量只能被赋值一次,所以当实例方法中含有对final变量的赋值操作时会报错。
初始化方式一,在定义变量时直接赋值
private final int i = 10;
初始化方式二,声明完变量后在构造方法中为其赋值,如果采用用这种方式,那么每个构造方法中都要有j赋值的语句
private final int i;
fun (int i){
this.i = i;
}
初始化方式三,声明完变量后在构造代码块中为其赋值。如果采用此方式,就不能在构造方法中再次为其赋值。构造代码块中的代码会在构造函数之前执行,如果在构造函数中再次赋值,就会造成final变量的重复赋值
private final int i;
{
this.i = 10;
}
在了解常见修饰符之前,我们需要对包有个概念
包用来存放类,类比于文件存放在目录中。
package 包名;//创建包
当类处在同一个包内时,可以相互调用,但当要调用包外的类时,则需要用关键字import,import语句一般出现在package语句后,class语句之前。
import java.util.*;
常见修饰符
比C++多的情况是,java多出了,默认标识符default,访问优先级由高到低依次是公有public、受保护protected、默认default、私有private。
局部变量不能被修饰符修饰。