JAVA从入门到精通-面向对象05
来源:互联网 发布:算法第四版mobi百度云 编辑:程序博客网 时间:2024/05/17 23:37
面向对象_01
云智科技学习笔记
面向对象概念
理解面向对象
l 面向对象是相对面向过程而言
l 面向对象和面向过程都是一种思想
l 面向过程
• 强调的是功能行为
l 面向对象
• 将功能封装进对象,强调具备了功能的对象。
l 面向对象是基于面向过程的。
面向对象的特点
l 是一种符合人们思考习惯的思想
l 可以将复杂的事情简单化
l 将程序员从执行者转换成了指挥者
l 完成需求时:
• 先要去找具有所需的功能的对象来用。
• 如果该对象不存在,那么创建一个具有所需功能的对象。
• 这样简化开发并提高复用。
举例:
人开门这个例子的分析过程:(名词提炼法)
门
{
门.开( ) { 操作门的具体操作 };
}
人
{
new门().开( );
}
面向对象开发,设计,特征
l 开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
l 设计的过程:其实就是在管理和维护对象之间的关系。
l 面向对象的特征:
• 封装(encapsulation)
• 继承(inheritance)
• 多态(polymorphism)
在以后的开发中,其实就是在找对象来用,如果没有对象,我们就创建对象。找对象,建立对象,使用对象,并维护对象之间的关系。
类与对象的关系
l 使用计算机语言就是不断的在描述现实生活中的事物。
l java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。
l 对象即是该类事物实实在在存在的个体。
类与对象(图例)
l 类与对象的关系如图
l 可以理解为:
1. 类就是图纸
2. 汽车就是堆内存中的对象
l 对于同一类事物可以抽取它们的共性的内容,定义在类中。
l 如生活中的汽车,每一台车都有轮胎数和颜色。
l 那么在通过java描述汽车这类事物时,就可以将这两个共性属性作为类中的属性进行定义。
l 通过该类建立的每一个汽车实体都具有该属性,并可以有对象特有的属性值。
类的定义
l 生活中描述事物无非就是描述事物的属性和行为。
• 如:人有身高,体重等属性,有说话,打球等行为。
l Java中用类class来描述事物也是如此
• 属性:对应类中的成员变量。
• 行为:对应类中的成员函数。
l 定义类其实在定义类中的成员(成员变量和成员函数)。
l 成员变量和局部变量的区别?
1. 成员变量:
• 成员变量定义在类中,在整个类中都可以被访问。
• 成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
• 成员变量有默认初始化值。
2. 局部变量:
• 局部变量只定义在局部范围内,如:函数内,语句内等。
• 局部变量存在于栈内存中。
• 作用的范围结束,变量空间会自动释放。
• 局部变量没有默认初始化值。
l 创建对象,使用对象
class Car//对Car这类事物进行描述
{
String color ="red";
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
class CarDemo
{
public static voidmain(String[] args)
{
Car c = newCar();//建立对象
c.color ="black";//对对象的属性进行修改
c.show();//使用对象的功能。
}
}
对象内存结构
Car c1 = newCar();c1.color="blue";
Car c2 = new Car();
只要是用new操作符定义的实体就在会堆内存中开辟一个新的空间。
并每一个对象中都有一份属于自己的属性。
通过对象.对象成员的方式操作对象中的成员,
对其中一个对象的成员进行了修改。和另一个对象没有关系。
匿名对象
l 匿名对象是对象的简化形式
l 匿名对象两种使用情况
• 当对对象方法仅进行一次调用的时
• 匿名对象可以作为实际参数进行传递
Java语言的强引用,弱引用,长引用,短引用?
封装(Encapsulation)
l 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
l 好处:
• 将变化隔离。
• 便于使用。
• 提高重用性。
• 提高安全性。
l 封装原则:
• 将不需要对外提供的内容都隐藏起来。
• 把属性都隐藏,提供公共方法对其访问。
private(私有)关键字
l private关键字:
• 是一个权限修饰符。
• 用于修饰成员(成员变量和成员函数)
• 被私有化的成员只在本类中有效。
l 常用之一:
• 将成员变量私有化,对外提供对应的set ,get方法对其进行访问。提高对数据访问的安全性。
构造函数
特点:
- 函数名与类名相同
- 不用定义返回值类型
- 没有具体的返回值。
作用:
对象一建立就会调用与之对应的构造函数,给对象进行初始化。
注意:
- 默认构造函数的特点。
- 多个构造函数是以重载的形式存在的。
- 当一个类中没有定义构造函数时,那么系统会对该类使用默认无参的初始化构造函数;但是当在类中显式定义了构造函数后,系统默认的构造函数就不存在了。
如下代码的编译出错:
class Demo
{
publicString name="aa";
Demo(Stringname){
this.name=name;
}
}
public class Construct1
{
publicstatic void main(String args[])
{
Democ=new Demo();
System.out.println(c.name);
}
}
错误提示为:
错误: 无法将类 Demo中的构造器 Demo应用到给定类型。说明该类使用的构造方法不能被初始化。即验证了默认的无参构造方法不存在了。
可以在一个类中定义多个构造函数,以重载的方式存在。以定义该类的不同初始化参数。
l 构造函数与一般函数的不同:
1. 写法上不同;
2. 运行上不同:
构造函数是在对象建立就运行,给对象初始化;而一般方法是对象调用才执行,给对象添加对象具备的功能。
3. 调用上不同:
一个对象建立,构造函数只执行一次;
而一般方法可以被该对象调用多次。
什么时候定义构造函数呢?
当分析事物时,当已初始化就应该具有某些方法和属性,就可以考虑构造函数。
构造代码块:
l 作用:给对象进行初始化,对象已初始化就运行,优先于构造函数。
l 构造代码块与构造函数的区别:
构造函数是对对象进行分别初始化,而构造代码块是对所有的对象进行初始化。
如下例子:
class Demo
{
publicstatic void main(String args[])
{
Personp=new Person("yedd");
System.out.println(p.getName());
Personp1=new Person();
}
}
class Person
{
privateString name="lisi";
Person(Stringname){
this.name=name;
}
//构造代码块
{
System.out.println("我是构造代码块");
}
Person(){}
publicvoid setName(String name)
{
this.name=name;
}
publicString getName()
{
returnthis.name;
}
}
当上述代码执行时,每次创建出来一个对象都会运行构造代码块,而只会调用相应的构造函数来初始化。
使用方法:
构建对象时,将对象共性的方法定义在构造代码块中。比如,每个小孩出生后,名字可能有或者没有,但是一定都有哭的动作。所以,是否定义名字可以放在不同构造函数里初始化,而哭的方法统一在构造代码块中执行。
this关键字
1. 特点:this代表其所在函数所属对象的引用。简单说,哪个对象在调用this,this就代表这个对象。
2. 换言之:this代表本类对象的引用。这是因为在该方法被调用前不确定哪个对象调用,所有采用this来替代。
什么时候使用this关键字呢?
1. 当在函数内需要用到调用该函数的对象时,就用this.例程。
2. This的应用:
当定义类中的功能时,当函数内部要调用该函数的对象时,这是用this来表示这个对象。但凡本类功能内部使用到该类时,都用this。
如下代码是对this关键字的应用:
public class Demo
{
publicstatic void main(String args[])
{
Personp1=new Person();
Personp2=new Person(30);
booleanb=p1.compare(p2);
System.out.println(b);
}
}
class Person
{
privateint age=30;
Person(){}
Person(intage){this.age=age;}
publicboolean compare(Person p)
{
if(this.age==p.age)
{
returntrue;
}else
{
returnfalse;
}
}
}
this语句在构造函数之间进行调用:
public class Demo2
{
publicstatic void main(String args[])
{
Personp1=new Person();
Personp2=new Person(30);
booleanb=p1.compare(p2);
System.out.println(b);
}
}
class Person
{
privateint age;
privateString name;
Person(){}
Person(Stringname){this.name=name;}
Person(intage){this.age=age;}
Person(Stringname,int age)
{
/*
this.name=name;//这个语句也可以用this关键字来在构造函数之间进行调用
//this(name);//相当于调用了Person(Stringname){this.name=name;}
//this.age=age;
this(age);//但是这个语句是不可以的,在使用this关键字时,必须是函数中的第一条语句
//如果像上面这么写会报错:错误: 对this的调用必须是构造器中的第一个语句
*/
//可以修改为这样:
//this.name=name;//这个语句也可以用this关键字来在构造函数之间进行调用
this(name);//相当于调用了Person(Stringname){this.name=name;}
this.age=age;
}
publicboolean compare(Person p)
{
if(this.age==p.age)
{
returntrue;
}else
{
returnfalse;
}
}
}
注意事项:
this关键字必须放在构造函数的第一个语句。因为初始化动作要先执行。
static(静态)关键字
static关键字:
• 用于修饰成员(成员变量和成员函数)
• 被静态修饰的成员变量称之为类变量,而普通变量称之为实例变量。
被修饰后的成员具备以下特点:
• 随着类的加载而加载
1. 在类初始化之前该静态成员已经存在了,同样会随着类的消失而消失,即它的生命周期与类相同。
• 优先于对象存在
1. 由于在类加载之前就已经存在了,所以可以用类名直接调用。
• 被所有对象所共享
• 可以被对象调用,还可以直接被类名调用
使用注意
• 静态方法只能访问静态成员,但是非静态方法可以访问静态资源也可以访问非静态资源。
• 静态方法中不可以写this,super关键字:因为静态资源优先于对象存在,所以静态方法中不能使用this.
• 主函数是静态的
实例变量与类变量的不同:
1. 存在位置不同:
类变量随着类的加载而加载存在于方法区或者叫共享区中,而实例变量存在随着对象的建立而存在于堆内存中。
2. 生命周期不同:
类变量的生命周期最长,随着类的消失而消失;实例变量生命周期随着对象的消失而消失。
静态修饰的利与弊:
1. 好处:对对象的共享数据进行单独空间的存储,节省空间,没有必要为每个对象开辟内存空间。
2. 坏处:生命周期过长,访问出现局限性。(静态虽好,但是只能访问静态资源。)
主函数是静态的详解:
主函数:
是一个特殊的函数,作为程序的执行入口,供JVM调用。
主函数的调用:
1. Public:代表该函数访问权限最大的。
2. Static :代表主函数随着类的加载就已经存在了。
3. Void:主函数没有返回值。
4. Main:不是关键字,但是是一个特殊的单词,可以被JVM识别。
5. (String args[]):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。
6. 主函数是固定格式的,供JVM识别调用。
深入剖析:
1. JVM在调用主函数是,传入的是newString[0];
System.out.println(agrs.length);既可以得以验证
2. 在两个启动运行类中可以使用该方式调用,并且可以传递参数:
classDemo
{
public static void main(String args[])
{
String []arr={"aaa","bbbb","ddd","ddfdfa"};
MainTest.main(arr);
}
}
classMainTest
{
public static void main(String args[])
{
for(inti=0;i<args.length;i++)
{
System.out.println(args[i]);
}
}
}
什么时候使用静态:
l 要从两个方面来入手:
因为静态修饰的内容要有成员变量和函数。
1. 什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态锁修饰,对象中的特有数据要定义成非静态存在于堆内存中。
2. 什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。
static修饰符的应用---工具类
1. 工具类的特点:
每个应用程序中都有共性的功能,就可以把这些功能单独抽取出来,独立封装,以便复用。
2. 请参看如下代码:
class ArrayTool
{
public void sort(int []arr)
{
for(inti=0;i<arr.length-1;i++)
{
for(intj=0;j<arr.length-i-1;j++)
{
swap(arr,i,j);
}
}
}
public static voidswap(int []arr,int a,int b)
{
int temp;
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
public void print(int []arr)
{
System.out.print("[");
for(inti=0;i<arr.length;i++)
if(i!=arr.length-1)
{
System.out.print(arr[i]+",");
}else
{
System.out.println(arr[i]+"]");
}
}
public int getMax(int []arr)
{
int max=arr[0];
for(inti=1;i<arr.length;i++)
{
if(max<arr[i])
{
max=arr[i];
}
}
return max;
}
public int getMin(int arr[])
{
int min=arr[0];
for(inti=1;i<arr.length;i++)
{
if(min>arr[i])
{
min=arr[i];
}
}
return min;
}
}
publicclass Demo
{
public static void main(String args[])
{
ArrayTool tool=newArrayTool();
int arr[]={1,5,4,2,5,25,55};
int b=tool.getMax(arr);
System.out.println(b);
}
}
发现这样写是有问题的:
1. 对象是用于封装数据的,可是在我们的工具类中并没有封装对象特有的数据。
2. 操作数组的每个方法都没有用到工具对象的特有数据。
3. 这时需要考虑,让程序更严谨,是不需要对象的,所以可以将工具类的方法定义成静态的。
可以对工具类的方法全部定义成静态的:
class ArrayTool
{
public static void sort(int []arr)
{
for(inti=0;i<arr.length-1;i++)
{
for(intj=0;j<arr.length-i-1;j++)
{
swap(arr,i,j);
}
}
}
public static void swap(int []arr,inta,int b)
{
int temp;
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
public static void print(int []arr)
{
System.out.print("[");
for(inti=0;i<arr.length;i++)
if(i!=arr.length-1)
{
System.out.print(arr[i]+",")
}else
{
System.out.println(arr[i]+"]");
}
}
public static void getMax(int []arr)
{
int max=arr[0];
for(inti=1;i<arr.length;i++)
{
if(max<arr[i])
{
max=arr[i];
}
}
return max;
}
public static void getMin(int arr[])
{
int min=arr[0];
for(inti=1;i<arr.length;i++)
{
if(min>arr[i])
{
min=arr[i];
}
}
return min;
}
}
public classDemo
{
public static void main(String args[])
{
int arr[]={1,5,4,2,5,25,55};
ArrayTool.getMax(arr);
System.out.println(b);
}
}
这样,可以方便于使用,但是该类可以被其他程序建立对象的。但是为了更严谨,可以对构造方法定义成private。
优化后的带按摩如下:
class ArrayTool
{ //构造函数私有化
private ArrayTool(){}
public static void sort(int []arr)
{
for(inti=0;i<arr.length-1;i++)
{
for(intj=0;j<arr.length-i-1;j++)
{
swap(arr,i,j);
}
}
}
public static void swap(int []arr,inta,int b)
{
int temp;
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
public static void print(int []arr)
{
System.out.print("[");
for(inti=0;i<arr.length;i++)
if(i!=arr.length-1)
{
System.out.print(arr[i]+",")
}else
{
System.out.println(arr[i]+"]");
}
}
public static void getMax(int []arr)
{
int max=arr[0];
for(inti=1;i<arr.length;i++)
{
if(max<arr[i])
{
max=arr[i];
}
}
return max;
}
public static void getMin(int arr[])
{
int min=arr[0];
for(inti=1;i<arr.length;i++)
{
if(min>arr[i])
{
min=arr[i];
}
}
return min;
}
}
Java文档的制作过程
1. 如果有一个工具类提供给我们使用,那么必须设置正确的classpath路径,可以通过如下命令行命令来设置:
Set classpath=.;你的类路径;这样就设置了一个临时类路径。
2. 如果是我们自己写的一个工具类提供给别人使用,那么必须要提供使用API,制作过程如下:
1. 给该工具类加上相应的注释;
2. 使用javadoc命令对该类进行文档生成。
如:该工具类制作如下:
/**
这是一个可以对数组进行操作的工具类,该类中提供了获取最值,
排序等功能。
@author 叶冬冬
@version V1.1
**/
public classArrayTool
{ //构造函数私有化
private ArrayTool(){}
/**
对一个整型数组进行排序
@param arr 整型的数组
**/
public static void sort(int []arr)
{
for(inti=0;i<arr.length-1;i++)
{
for(intj=0;j<arr.length-i-1;j++)
{
swap(arr,i,j);
}
}
}
/**
对一个整型数组中指定的元素位置进行置换
@param arr 整型数组
@param a 要交换的位置
@param b 要交换的位置
**/
public static void swap(int []arr,inta,int b)
{
int temp;
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
/**
打印输出数组的元素,打印格式为 [element1,element2,,...]
@param arr 整型数组
**/
public static void print(int []arr)
{
System.out.print("[");
for(inti=0;i<arr.length;i++)
if(i!=arr.length-1)
{
System.out.print(arr[i]+",");
}else
{
System.out.println(arr[i]+"]");
}
}
/**
获取整型数组中的最大值
@param arr 整型数组
@return max 最大值
**/
public static int getMax(int []arr)
{
int max=arr[0];
for(inti=1;i<arr.length;i++)
{
if(max<arr[i])
{
max=arr[i];
}
}
return max;
}
/**
获取整型数组中的最小值
@param arr 整型数组
@return min 最小值
**/
public static int getMin(int arr[])
{
int min=arr[0];
for(int i=1;i<arr.length;i++)
{
if(min>arr[i])
{
min=arr[i];
}
}
return min;
}
}
使用如下命令进行文档生成:
Javadoc –d myhelpArrayTool.java –author –version
命令说明:
Javadoc:是jdk中提供的文档制作工具,可以生成java类的API文档
-d:表示生成一个目录,如果没有显式指定绝对路径,则在当前路径下生成
myhelp:当前路径下生成存放java文档的目录
ArrayTool.java:需要生成java文档的原文件
-author:在该类的声明注释中提取作者信息
-version:在该类的声明注释中提取版本信息
静态代码块
1. 格式:
static
{
静态代码块的内容;
}
2. 特点:
随着类的加载而执行,只执行一次,并优先于主函数,用于给类进行初始化。
请看如下代码的打印结果:
class Demo
{
public static voidmain(String args[])
{
System.out.println("b");
new Demo();
System.out.println("c");
new Demo();
System.out.println("over");
}
static
{
System.out.println("a");
}
}
3. 打印结果如下:
a
b
c
over
4. 说明了:
1. 静态代码块优先于main函数执行;
2. 静态代码块执行一次。
注意:
在上面的例子中:
Demo d=null;//这种情况下,静态代码块是不会被加载的
D=new Demo();//只有类被使用了,才会调用静态代码块
5. 总结:
class Demo
{
public static voidmain(String args[])
{
Demo1 d=newDemo1(6);
}
}
class Demo1
{
int age=4;
//构造函数
Demo1()
{
System.out.println("构造函数。。。没有age");//上面的初始化时,该构造函数没有被调用
}
Demo1(int age)
{
this.age=age;
System.out.println("构造函数。。。age");//该构造函数被调用,优先级最低
}
//构造代码块
{
System.out.println("构造代码块");//初始化类时被调用,优先级次高
}
//静态代码块
static
{
System.out.println("静态代码块");//初始化时被调用,优先级最高
//System.out.println("静态代码块"+this.age);//在静态代码块中不能访问非静态资源
}
}
6. 运行结果如下:
静态代码块
构造代码块
构造函数。。。age
1. 说明了在一个类中,静态代码块的执行优先级最高,构造代码块次之,构造函数最低。
2. 同时在静态代码块或者静态方法中不能访问非静态资源。
对象初始化过程:
l Person p=new Person(“zhangsan”,23);这个语句都做了什么呢?
1. 因为new 用到了Person.class,所以会先找到Person.class文件并加载到内存中;
2. 执行该类中的static代码块,如果有的话,给Person.class类进行初始化;
3. 在对内存中开辟空间,分配内存地址;
4. 在对内存中建立对象的特有属性,并进行默认初始化;
5. 对对象的特有属性进行显示初始化;
6. 对对象的属性进行构造代码块的初始化;
7. 对对象进行对应的构造函数的初始化;
8. 将内存地址赋值给栈内存中的p变量。
l 对象方法被调用过程
l 完成对类的初始化,此时在方法区中加载了静态方法和各个成员方法;
l 对象的成员方法被调用过程:
1. 当某个成员方法被调用时,将该方法在栈内存中建立函数调用栈,并将函数参数传递进去,其中this也是作为一个参数传递到函数栈中,指向该类初始化对象在堆内存中的引用;
2. 然后通过函数执行操作堆内存中的成员属性;
l 类的静态方法被调用过程:
1. 在方法区中的静态方法是通过类名来直接调用的,由于它优先于对象而存在,所以只能通过类名来调用,同时由于此时没有建立对象引用,所以不能操作对象的特有属性。
- JAVA从入门到精通-面向对象05
- Java学习从入门到精通(八/八)面向对象、java.util 问答篇
- Java学习从入门到精通(八/八)面向对象、java.util 问答篇
- JAVA从基础到精通(面向对象)
- JAVA从入门到精通(8)---类和对象
- Java从入门到精通_2 对象和类
- Java从入门到精通第七章类和对象
- Java从入门到精通Chapter7_3对象比较
- JAVA从入门到精通
- JAVA从入门到精通
- JAVA从入门到精通
- java 从入门到精通
- Java从入门到精通
- java从入门到精通
- java从入门到精通
- Java从入门到精通
- java从入门到精通
- 源码-PL/SQL从入门到精通-第十七章-面向对象编程-Part 1
- Qt 实现无标题窗口的移动
- SDWebImage库的理解
- Linux实现Cisco风格ACL之空想
- 中断处理过程
- 经典网页设计:超炫的动画效果单页网站设计
- JAVA从入门到精通-面向对象05
- 为啥spinlock里面不能sleep
- LAMP环境的搭建
- UVa 10010 - Where's Waldorf?
- ubuntu 窗口没有了“关闭”“最小化”“最大化“按钮
- 试图搞懂MDK程序下载到flash(六)--DNW+supervivi+MDK下载到Nand Flash
- CSS3中和动画有关的属性transform、transition 和 animation
- windows与linux复制文件(类似于linux的scp工具)
- 关于路由的递归查询