目录
点击传送》》》
前言:
1、面向对象概述
2、类和对象
1、对象
2、类
3、类的定义格式
1、成员变量(静态部分)
2、成员方法(动态部分)
3、实例化
3、权限修饰符
1、private
2、public
3、protected
4、default
4、局部变量
5、this关键字
3、类的构造方法
4、static:静态变量、常量、方法
1、static关键字
2、static修饰的代码块
3、面试题
前言:
在java语言中经常被提到的两个词是类和对象。它是面向对象的基本。实际上,类可以看做是对象的载体,也就是说类是对象所具有的属性,也可以说类是定义对象的基本规范。
1、面向对象概述
由来:早期的计算机编程是基于面向过程的方法,例如实现算术运算1+1+2 = 4,通过设计一个算法就可以解决当时的问题。但是随着软件规模越来越庞大,处理过程越来越复杂,这种面向过程的结构化语言的弊端也就逐渐暴露出来,开发周期也越来越长,产品质量不尽人意。这时人们开始引入另一种开发思想--面向对象。
一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承,帮助人们实现对现实世界的抽象与数字建模。通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木一样快速开发出一个全新的系统。面向对象是指一种程序设计范型,同时也是一种程序开发的方法。对象是类的具体化实现。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。
2、类和对象
1、对象
静态部分和动态部分。
举例:
注意看这个篮球巨星,仔细分析可以知道
静态属性有 》 角色:偶像练习生 ,
发型:中分,
穿着:背带裤
.........
动态属性有 》 胯下运球,铁山靠 ........ 等一些专业动作指导。
而在计算机世界中,我们可以根据对象在现实世界中所具有的属性将其抽象出来,在识别这个对象的属性后,这个对象就被定义完成了,然后可以根据这个对象的属性来制定具体的解决问题的方案,这就是对象。
2、类
类
在java语言中,类中对象的动态属性是以方法的形式定义的,对象的静态属性是以成员变量的形式定义的,所以类包括对象的静态和动态属性。
3、类的定义格式
// 创建类
//class ClassName{
// field; 字段(属性) 或者 成员变量
// method; 行为 或者 成员方法
//}
// 例如定义手机类
class Phone{
String SizeOfPhone;
String CpuModel;
int DateOfManufacture;
//.......等等静态部分
public void function_TakeAPicture(){
System.out.println("正在拍照");
}
// ......等等动态部分
}
根据上面的代码,使用者可以用class来定义一个手机对象(这里为了和对象名进行区分,推荐使用大驼峰的形式来书写类名),Phone为类名,同时在Phone这个类中定义了他的属性,我们可以看到,静态属性是用变量来进行定义的,动态属性是以方法来定义的:
1、成员变量(静态部分)
例如,手机尺寸,我们用字符串来定义:String SizeOfPhone; SizeOfPhone 为变量名,也可以是java中其他合法数据类型:
例如: Boolean类型 等等。我们可以为其设置初始值,String SizeOfPhone = "长 x 宽 x 高 " ;
但也可以不初始化,不初始化就会自动初始化为默认值,Boolean类型的默认值为 false,int float等默认值为其对应的0值,int为0,float为0.0等,String类型默认为 null,等。
2、成员方法(动态部分)
在java语言中,使用成员方法对应于类的对象的行为,就像上述手机这个类中的华为手机拍照这个行为一样,其定义成员方法的格式如下:
权限修饰符 返回值类型 方法名
......... //方法体
return
}
return
注:如果一个类的方法中如果有与成员变量 同名的局部变量,则方法的执行以局部变量来进行
3、实例化
了解什么是类,什么是对象后,就该了解一下什么是实例化。
我们使用上面的方法创建一个类之后,就有了我们所定义的类的属性,然后使用这个类去创建一个对象,这个过程就称为实例化,例如,我们定义了一个手机类,那么我们就可以使用这个手机类创建一个名为华为手机的具体对象。
在java中 采用 new 关键字来实例化生成对象。
我们这里拿一个狗类来举例 :
new关键字的使用部分: PetDog dog1 = new PetDog();
PetDog dog2 = new PetDog();
这里就实例化了两个PetDog的对象:dog1和dog2 。(可以通过英文字符中的点好' . '来访问对象的中的成员)
3、权限修饰符
在初学java的时候,不免会看到public,private等修饰符,那么这些关键字都有些什么作用呢,经过学习我们可以了解到,这些都是java中的权限修饰符,主要包括private, public, protected,这些修饰符控制对类和类的成员的访问。
1、private
如果一个类的成员被private修饰,则该成员只能在其所在的类中访问:
class Dog{
private String name;
int age;
public void bark(){
System.out.print(name + "is barking!");
}
}
这里我们在main函数里面试试访问他:结果是显示在编译的时候出现了问题
java: name 在 Dog 中使 private 访问控制
private修饰一个类成员变量无法直接同一个包的不同类中访问
在其后面要讲到的继承的子类中也是不可用的(这个被private修饰的父类成员,可以被继承但是无法访问):
class Dog{
private String name;
int age;
public void bark(){
System.out.print(name + "is barking!");
}
}
class specialDog extends Dog{
public void func(){
System.out.println("the sepcial dog");
}
}
public class Test {
public static void main(String[] args) {
specialDog dog1 =new specialDog();
dog1.name = "修勾";
}
}
我们定一个Dog父类,然后使用specialDog来继承这个Dog父类,然后创建一个specialDog的对象并对父类中的name进行访问:结果同样如下。
无法访问所继承的父类中的private修饰的成员
除此之外,被private修饰的成员对其他包的类也是不可见的:编译出错。
父类和子类在不同的两个包
设置private可以避免用户直接访问它,从而保证数据的安全性,如果非要在外部调用这个类中被private修饰的成员,可以在这个类中开放一个指向这个private修饰的成员的接口方法,
2、public
类中被public修饰的成员,除了可以在本类访问这个成员,在其他类和子类,或者其他包中访问。
此处的案例在private中可以类比,不再一一列举。
3、protected
从上面的内容可以得知,类中private修饰的成员不能夸包访问,而public又可以给到最大权限,可以夸包访问,在不同的类中也可以使用,两种修饰符都太极端,于是就给出了一个中间值,他就是protected,类中被protected修饰的变量可以在同一包中的同一类访问,也可以在同一包中的不同类访问,同时还可以在不同包中的子类访问。
4、default
如果不加修饰符,则默认给出defualt修饰符,defualt修饰符默认只能同一包中的同一类和同一包中的不同类访问。即只有同一个包中的类可以调用这个类的成员。
4、局部变量
和c语言相比,java中的类的结构与c语言中的结构体类似,在java语言中,一个在类中、在方法外定义的变量称为成员变量,在类中定义的方法,称为成员方法,而在成员方法(外加普通方法)中定义的变量为局部变量。
局部变量的有效范围是在当前代码块的,例如:有这样一段代码
public static void function(int[]arr){
int i = arr.length;
for (int j = 0; j < i - 1; j++) {
for (int k = 0; k < j-1; k++) {
if( arr[j]> arr[k]){
int tem = arr[j];
arr[j] = arr[k];
arr[k] = tem;
}
}
}
}
其中的i就为局部变量,j和k也是局部变量,只不过他们两个的作用范围都被限制在了for循环语句中,他们的作用范围如图:
其中的int[ ] arr 其实也是一个局部变量,他的作用范围为整个方法的内部
注意:类中成员变量不不赋值的话都会有一个默认值,这在前面的已经提过,但是如果是局部变量在定义的时候没有赋值(初始化)的话就会编译报错。
5、this关键字
在学习了局部变量的时候,结合private我们可以提出这样的一个问题,如果类中方法的传入的参数和我们要去修改的被private修饰的成员名一样的话会如何赋值,例如:在这个狗类中
class Dog {
private String name;
int age;
public void dis(String name){
name = name;
}
public void GetName(){
System.out.println(name);
}
}
class specialDog extends Dog {
public void func() {
System.out.println("the sepcial dog");
}
}
public class Test{
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.dis("修勾");
dog1.GetName();
}
}
我们修改dog1为继承了Dog的specialDog的对象,这里利用接口函数去修改他的name然后获取这个(打印)name:结果如下
null
显然是这个地方除了问题,有两个name,一个是Dog类中成员变量name,一个是Dog类中方法的局部变量name,编译器就默认name为局部变量中的类。
如果遇到这种情况该如何区分是局部变量还是成员变量中的变量呢? 在java语言中规定使用this关键字来代表本类的对象的引用,我们将上述代码中的 name = name 改为:
this.name = name
编译器就会区分,原来前面这个name指的是这个类中的成员变量。
修改后的运行结果:
如果没有加this关键字,就相当于把局部变量的name赋值给自己,然后成员变量的name没有被初始化,给出的默认值为null,打印结果就为null。在后面还会讲到this的其他用法。
3、类的构造方法
从我们上面的例子可以看出来,我们定义一个对象,初始化赋值过程都是在创建完对象之后赋值,那有没有一种办法可以在创建对象结束之前就可以赋值呢?答案是肯定的。
构造方法。每当我们实例化一个对象的时候,就会自动调用构造方法,(如果没有自己手动写构造方法,就会自己调用一个内容为空的构造方法,即一个不带参数的构造方法)
构造方法有如下几个特点:
1、构造方法没有返回值
2、构造方法名称要与其类名相同
3、在定义构造方法的时候,构造方法没有返回值,如普通方法不同的是,构造方法不用在前面加上void返回类型的字样。4、类中默认提供一个不带参数的构造方法
5、如果自己提供了一个构造方法,那么编译器默认不再提供不带参数的构造方法。
如果自己提供了一个不是不带参数的构造方法,那么当你企图用一个无参构造方法去实例化一个对象的时候就会报错,因为他在里面找不到不带参数的构造方法,此时编译报错。
其语法格式如下:
class A{
public A(){
..... // 构造内容
}
}
举例:
class Dog {
private String name;
int age;
public Dog(String name,int age){
this.name = name;
this.age = age;
System.out.println("狗名为:"+this.name);
System.out.println("狗龄为:"+this.age);
}
}
public class Test{
public static void main(String[] args) {
Dog dog1 = new Dog("修勾",5);
}
}
结果为:
事实上,this也可以调用类中的构造方法,看实例:
class Dog {
private String name;
int age;
public Dog(String name){
this.name = name;
System.out.println(this.name);
}
public Dog(){
this("this调用无参构造方法");
System.out.println("无参构造方法");
}
}
public class Test{
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
其调用顺序为:
除了构造方法以外,更方便的也可以直接进行对成员变量的幅值,这样就修改了成员变量的初始值。后面仍然可以对其进行赋值操作。
同时,构造方法也支持重载,在传入不同的参数需要对应做出不同的反应的时候,这个时候就可以将构造方法重载。
4、static:静态变量、常量、方法
1、static关键字
我们知道,不同的对象有不同的属性,这些属性包括动态属性和静态属性(这里的静态属性不是值得静态static修饰的属性,而是类的成员变量)。但是我们在处理问题的时候,可能会遇到不同对象要使用同一个数据的情况,就比如设计一个球类和圆类,他们在计算的时候都会需要用到一个PI(π)常量,如果用常规方法在这两个类中都定义一个PI成员,系统就会将这两个不在同一个类的成员分配到不同的内存中造成空间浪费。为了解决这个问题,可以使用static关键字,将这个常量设置为静态的。用图表示为:
由static修饰的成员属于类所有,同时这个成员不再依赖于对象,可以直接使用这样的语法形式来访问这个static修饰的成员:
类名.被static修饰的成员
也可以使用对象.static成员的方法来使用,但是不推荐,因为对象. 的形式访问是面向对象的常用访问方法,在这里容易错误的将static成员看成非static成员。
static修饰的成员仍然受权限修饰符的限制。
注意:
静态方法中无法使用this关键字
this是在实例化一个对象的时候使用,然后静态成员或者方法是在类形成的时候就创建的,因此静态方法不能直接使用非静态方法。
2、static修饰的代码块
在使用任何被static修饰的变量的时候,或者是在使用某些方法之前,需要初始化static变量,为了除了这种情况,java提供了static修饰的代码块,在加载类的时候就执行,初始化这些变量,以达到这种需求:
class Dog {
public static String name;
public static int age;
static{
name = "xiaoli"
age = 5
}
}
static修饰的成员成为静态成员,被static修饰的语句或者语句块成为静态语句或者静态代码块。
在实例化一个对象的时候,所有静态代码块会首先依次执行完,在第二次创建对象的时候这个这些被static修饰的语句或者代码块不会再执行。
class Dog {
public String name;
public int age;
static{
System.out.println("静态代码块执行");
}
{
System.out.println("实例代码块执行");
}
public Dog(String name,int age){
System.out.println("构造代码块执行");
this.name = name;
this.age = age;
System.out.println("狗名为:"+this.name);
System.out.println("狗龄为:"+this.age);
}
}
public class Test{
public static void main(String[] args) {
Dog dog1 = new Dog("修勾",5);
Dog dog2= new Dog("大狗",8);
}
}
运行结果为:
可以看出来,静态代码块在构造方法之前执行,且只会执行一次,第二次创建对象的时候不会再执行。实例代码块在静态代码块之后,构造方法之前执行,但是实例代码块每次在创建对象的时候都会执行。
3、面试题
为了让读者更好的理解静态方法的使用,请看例题:
下面关于静态方法说明正确的是
A.在静态方法中可用this来调用本类的类方法
B.在静态方法中调用本类的静态方法时可直接调用
C.在静态方法中只能调用本类中的静态方法
D.在静态方法中绝对不能调用实例方法
解析:
静态方法中没有this关键词,因为静态方法是和类同时被加载的,而this是随着对象的创建存在的,静态比对象优先存在,因此选项A错误。也就是说,静态可以访问静态,但静态不能访问非静态而非静态可以访问静态。
在静态方法中可直接调用本类的静态方法,也可以通过类名.静态方法名的方式来调用其他类的静态方法,选项C错误。
D选项,静态方法不能直接调用实例方法和对象,但可以通过在静态方法中创建类的实例的方式间接调用
本次内容完........