-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、面向对象基本概念
在Java的开发过程,其实就是不断的创建对象,使用对象,指挥对象做事情。设计的过程,其实就是在管理和维护对象之间的关系。
面向对象的三个特征:
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
开发中:其实就是找对象使用,没有对象,就创建一个对象!
成员变量和局部变量 区别在于作用范围不同
之前我们用到的基本都是局部变量,现在我们将会使用成员变量。其实它两都是变量,规范写法上也没啥区别,都是标识符,但是在作用范围和内存中分配不同。
区别:
成员变量 | 局部变量 |
---|---|
成员变量定义在类中,在整个类中都可以被访问。 | 局部变量只定义在局部范围内,如:函数内,语句内等。 |
成员变量随着对象的建立而建立,存在于对象所在的堆内存中。 | 局部变量存在于栈内存中。 |
成员变量有默认初始化值。 | 作用的范围结束,变量空间会自动释放。 |
局部变量没有默认初始化值。 |
匿名对象:
匿名对象是对象的简化形式。
匿名对象两种使用情况
1、当对对象方法仅进行一次调用的时
2、匿名对象可以作为实际参数进行传递
注:如果对一个对象进行多个成员调用,必须给这个对象起个名字。
对象的封装
1、 概念
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
2、 好处
a)将变化隔离。
b)便于使用。
c)提高重用性。
d)调高安全性。
3、 原则
a) 将不需要对外提供的内容都隐藏起来。
b) 把属性都隐藏,提供公共方法对其访问。
4、 封装的表现形式之一——private(私有)
private关键字:权限修饰符;用于修饰类中的成员(成员变量,成员函数);私有只在本类中有效。
注意: 将成员变量私有化,对外提供对应的set,get方法对其进行访问之所以在对外提供访问方式,就因为可以在访问方式中加入逻辑判断语句,以便提高程序安全性!!
比如: private int age;
public int setAge(int a)
{ if......
......
else age=a;
}
构造函数
构造函数式在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,给是对象添加对象具备的功能。一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。
特点:
a) 函数名与类名相同。
b) 不用定义返回值类型。
c) 不可以写return语句。
作用:
给对象进行初始化。
构造函数的小细节:
当一个类中没有定义构造函数时,那么系统就会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就没有了。
注意:当类中重载了构造函数,而且没有定义空参构造函数时,那么以后每次创建对象时必须按照重载的构造函数去创建新的对象!
什么时候定义构造函数?
当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。
6、构造代码块
作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数运行。
和构造函数的区别:
构造代码块是给所以对象进行初始化。
而构造函数是给对应的对象初始化。
构造代码块中定义的是不同对象共性的初始化内容。
this关键字
this代表它所在函数所属对象的引用。
谁调用this所在的函数,this就代表哪个对象。
this的应用:
当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用到了本类对象,都用this表示。
this语句:
用于构造函数之间进行互相调用。如:this(name);
thi语句只能定义在构造函数的第一行。因为初始化要先执行
注:一般函数不能直接调用构造函数,因为this语句不能用在一般函数中,只能用在构造函数间。
static(静态)关键字
static是一个修饰符,用于修饰成员(成员变量和成员函数)。当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员。
static特点:
1、随着类的加载而加载。
也就是说:静态会随着类的消失而消失,说明它的生命周期最长。
2、优先于对象存在。明确一点:静态是先存在。对象是后存在。
3、被所有对象所共享。
4、可以直接被类名所调用。
由于静态成员可以直接被类名调用,因此静态成员变量又称为类变量。而非静态成员变量又被称为实例变量。
实例变量和类变量的区别:
1、存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
2、生命周期。
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
静态有利有弊:
利处:单独存储,节省空间,可以直接被类名调用。
弊端:生命周期过长 访问出现局限性
jvm在调用主函数时,传入的是new String[0];
string[ ] args 传值练习!!
class args
{
public static void main(String[] args)
{
System.out.println(args[0]); //java args练习,java args test-args
System.out.println(args.length); //等到args的长度
}
}
输出结果:
静态使用注意事项:
1 静态方法只能访问静态成员,非静态方法既可以访问静态也可以访问非静态。
2 静态方法中不可以定义this,super关键字, 因为静态优先于对象存在。所以静态方法中不可以出现this。
3 主函数是静态的。
4 当对象中出现共享数据时,该数据被静态所修饰。
5 对象中的特有数据要定义成非静态存在于堆内存中
6 当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。
静态代码块:
格式:
static
{
.........
}
特点:随着类的加载而执行,执行一次。并优先于主函数。用于给类进行初始化。
工具类
如果一个类中定义的方法没有封装特有数据,那么可以将此类定义为工具类,而且通常会将工具类中的方法定义为static方法!
当方法都静态后,为了更加严谨,将空参构造函数私有话,以便于该类无法建立新对象
对象的初始化过程: 定义一个新对象都做了哪些事情?
1、把类名.class文件加载到内存中。
2、执行该类中的static代码块,如果有得话,给该类进行初始化。
3、在堆内存中开辟空间,分配内存地址。给对象
4、在堆内存中建立对象的特有属性。并进行默认初始化。
5、对属性进行显示初始化。
6、对对象进行构造代码块初始化。
7、对对象进行对应构造函数初始化。
8、将内存地址赋给栈内存中的对象名变量。
如图,打印顺序为 1-2-3-4
静态代码块&构造函数&构造代码块区别
静态代码块:
随着类的加载而执行,只执行一次,并优先于主函数,也优先于构造代码块。用于给类进行初始化。
构造函数“
构造函数是在对象一建立就运行,给对象进行初始化。
构造代码块:
构造代码块是在对象一建立就运行,而且优先于构造函数执行,用来定义不同对象共性的初始化内容。
区别
构造代码块与构造函数区别:构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化。
构造代码块与静态代码块:随着类的加载静态代码块只执行一次,构造每次建立对象都会执行 !
代码执行顺序:“静态代码块”>“构造代码块”>“构造函数”。
静态的应用——文档说明书。
@auhor
@version
@param arr
@return
在dos命令行中输入命令:javadoc -d Myhelp -author-version arrayToo.java
其中-d myhelp 表示创建myhelp目录(注意是在java文件夹的同目录下)
-author 和-version 表示生成作者和版本
Java中的javadoc工具就会帮我们完成说明文档也称API的制作。
设计模式----单例设计模式(饿汉式与懒汉式)
单例设计模式的作用:使一个类在内存中只存在一个对象。 (EditPlus中背景颜色的设置就是单例设计模式的体现)
用代码实现单例设计模式需要做三部:
1、将构造函数初始化。
例:private Single(){}
2、在类中创建一个本类对象。
例:private static Single s= newSingle();
3、提供一个访问方法可以获取到该对象。
例:public static Single getInstance()
{
return s;
}
单例设计模式有两种写法:
1、饿汉式:Single类一进内存,就已经创建好了对象。在实际开发中,出于安全考虑,建议使用饿汉式。
完整代码如下:
class Single
{
private static Single s=new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
class Single
{
private static Single s=null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s=new Single();
return s;
}
}
懒汉式想要消除安全隐患可以这样写:
//懒汉式安全版
class Single
{
private static Single s=null;
private Single(){}
public static Single getInstance()
{
if(s==null)
synchronized() //加上安全锁,如果为空可以排队一个个进去
{
if (s==null)
{
s=new Single();
}
}
return s;
}
}
继承
特点
1、提高了代码的复用性。
2、让类与类之间产生了关系。有了这个关系,提供了多态的前提。
注意:Java语言中,只支持单继承,不支持多继承。例:一个儿子只能有一个父亲。
原因:因为类与类多继承的话,容易带来安全隐患。如:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪个一个。
但是Java保留了这种机制,并用另一种体现形式来完成。叫多实现。
super的使用和this的使用几乎一致,且两者都存在于方法区中。
this表示本来对象的引用。
super表示父类对象的引用。
2、函数——覆盖
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中。但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。子类同时具有父类方法中的内容时,可以用super.方法();
注意:1、子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2、静态只能覆盖静态。
3、父类中的私有方法不能被重写。
4、子父类中相同名函数不能返回不同类型值
小知识点:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。
子类中 构造函数特征:
在对子类对象进行初始化时,子类的每一个构造函数默认第一行有一条隐式的语句super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函数:
因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。
所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。在上面的示例中已经有了很好的体现。
注:super语句一定定义在子类构造函数中的第一行。
注意:如果父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数
小知识点:
为什么this()和super()不能在同一个构造函数中?
因为它们两个都必须出现在第一行!
为什么必须出现在第一行?
因为初始化动作要先做。
1、表示对当前对象的引用!
2、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!
知识点:final关键字
继承的出现,打破了对象的封装性,使得子类可以随意复写父类中的功能。
这也是继承的一大弊端。 为了解决这一弊端 ,介绍java新的关键字——final(最终)。
final作为一个修饰符。具有以下特点:
1、可以修饰类、函数、变量。
2、被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。
3、被final修饰的方法不可以被复写。
4、被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。
5、内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
抽象类
抽象类的特点
1、抽象类和抽象方法必须用abstract关键字来修饰。
2、抽象方法只有方法声明,没有方法体,定义在抽象类中。
3、 抽象类不可以被实例化,也就是不可以用new创建对象。
4、抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。
抽象类与一般类的区别
1、事物中出现了一些不知道具体内容的方法部分。无法定义主体。通过抽象方法来表示。
2、抽象类比一般类多了个抽象函数。就是在类中可以定义抽象方法。
3、抽象类不可以实例化。
4、抽象类虽然不能创建对象,但是也有构造函数。供子类实例化调用。
注意:抽象类中可以一个抽象方法方法都没有。
注意:1、被abstract修饰的函数不能同时被private、final、static修饰。
原因:
final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
private:抽象类中的私有的抽象方法,不被子类所知,就无法被复写。
而抽象方法出现的就是需要被复写。
static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。
可是抽象方法运行没意义。
小练习: 利用抽象类 写一个获取一段程序的运行时间小程序 ,大家自己想想吧
接口
一、概述
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。格式为:
interface 接口名{}
子类名 implements接口名{}
格式特点:
1、接口中常见定义:常量,抽象方法。
2、接口中的成员都有固定修饰符。
常量:public static final
方法:public abstract
3、 接口中的成员都是public的。
在使用中,常量可以不写public static final,方法可以不写publicabstract,编译时Java会自动添加这些修饰符,因为这是固定的格式修饰符。但为了方便阅读,通常我们都写上。
二、特点
1、接口是对外暴露的规则。
2、接口是程序的功能扩展。
3、接口的出现降低耦合性。
4、接口可以用来多实现。这也是对多继承不支持的转换形式。java支持多实现。
5、类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
6、 接口与接口之间可以有继承关系。而且可以多继承。
注意:1、接口不可以创建对象的,因为有抽象方法。需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。
2、实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写。
三、接口与抽象类区别
1、抽象类体现继承关系,一个类只能单继承。
接口体现实现关系,一个类可以多实现。同时接口与接口之间有继承关系。
2、抽象类是继承,是 "is a "关系。
接口是实现,是 "like a"关系。
3、抽象类中可以定义非抽象方法,供子类直接使用。
接口的方法都是抽象,接口中的成员都有固定修饰符。
4、抽象类中可以私有变量或方法。
5、接口可以继承接口,接口之间可以实现多继承(extends)。