------------ android培训、java培训、期待与您交流! -------------
面向对象的特征:封装、继承、多态
面向对象特点:
1、 面向对象是将功能封装,强调了具备功能的对象,
2、 面向对象是基于面向过程的。将复杂事情变简单、将执行者转变为指挥者、人开门(开门的方法的属于门的) ps:去买电脑,自己不懂就要咨询,上网查资料,这个过程很麻烦,但是可以找个懂电脑行情的人,就可以调用他的方法,变的简单
最牛的例子是到哪到说到哪,灵活利用现实的环境,会拍马屁,推销自己。
名词提炼法:
以后的开发就是找对象,没对象创建对象。找对象,建立对象,使用对象。维护对象的关系。
——/*类与对象的关系(鸡生蛋、蛋生鸡的关系),类就是对现实生活中事物的描述,对象:就是这类事物的,实实在在存在的实体,*/——
类: 就是描述事物,就是定义属性(成员变量)和行为(function),回顾内存这部分知识,注意多引用指向同一个对象
注意:成员变量和局部变量的区别,存储区域、作用域,特点(图纸的颜色和汽车的颜色的区别)匿名对象:是对象的简写格式。使用情况:
1、当对对象方法仅调用一次时(new car().run();调用对象方法有意义,属性没意义),
2、匿名对象可以作为实际参数进行传递——凡是简化的都有局限性。
封装(encapsulattion):
隐藏(通过权限修饰符)对象的属性和实现细节,仅对外提供公共的访问细节。好处:将变化隔离、便于利用、提高重用性、提高安全性。封装原则:1、将不需要的内容都隐藏起来。2、把属性都隐藏,提供公共方法对其访问————(招聘一个员工,分配下去任务后,只要结果,不要过程,程序员自己的开发心酸什么的都隐藏,类似于电脑主机,将芯片。显卡。主板。风扇封装,对外提供插口访问主机功能)
Private:私有,权限修饰符,,用于修饰类中的成员(成员变量、成员function),私有只在本类中有效。一个成员变量,通常有两个方法(一个get,一个set),可以通过逻辑语句控制输入的数据,来实现封装,增强健壮性。注意:私有仅仅是封装的一种表现形式。
构造函数:
a) 特点: 1、函数名与类名相同(包括大小写)。2、没有返回值。3、没有return语句。
b) 作用:对对象进行初始化(对象一建立,就会调用与之对应的构造函数)
c) 注意:1、默认空参的构造函数的特点(自定义了构造函数后,默认构造函数就没了)。2、多个构造函数是以重载的形式出现的 3、构造函数不存在继承,也就没有覆盖,但是可以通过this(),或super()相互调用
构造代码快(定义不同对象共性的初始化内容)
a) 作用:给对象进行初始化
b) 对象一建立就运行,而且优先于构造函数。
c) 和构造函数的区别:构造代码块是给所有对象进行初始化,而构造函数是对对应的对象进行初始化
this关键字
a) 当局部变量与成员变量的名字相同时,前者隐藏掉后者,要用到this,代表所在函数所属(本)对象的引用。
b) This语句:用于构造函数之间的调用(ps:构造一个人,只有姓名。构造另一个人,同时赋予姓名和年龄。
就可以通过this(name)调用另一个构造函数——)
c) This()语句只能定义在构造函数的第一行;因为初始化要先执行!!
static关键字:
是一个修饰符,只能用于修饰成员(成员变量、成员function),提取到另外一个内存空间,对象都可以直接调用, 省内存
特点: a)、随着类的加载而加载,随着类的消失而消失,生命周期最长;
b)、优先于对象的存在,不建议定义过多的静态变量。
c)、被所有对象调用。静态多了一种调用方式:类名 . 静态成员;
方法区(共享区、数据区):存放类中的方法、类中的共享数据。
类变量和实例变量的区别:
a、类变量随着类的加载而存在于方法区中,随着类的消失而消失,实例变量随着对象的建立而存在于对内存中。
b、类变量生命周期最长,实例变量随着对象的消失而消失。
静态的使用注意事项:
1)静态方法只能只能访问静态成员,非静态既可以访问静态也可以访问非静态,
2)静态方法中不可以定义this,super关键字,因为,静态优先于对象存在
静态的利弊:
对对象的共享数据进行单独存储,节省空间。可以直接类名调用。生命周期长,访问有局限性,静态只能访问静态
什么是主函数:public static void main(String[] args0主函数是一个特殊的函数,作为程序的入口,被JVM调用
主函数的定义:public、代表着该函数的访问权限最大。static、代表着主函数随着类的加载就已经存在了。void、主函数没有具体返回值(虚拟机接收到返回值会“害怕”)。main:不是关键字,但是可以被JVM识别。主函数是固定格式,可以被JVM识别。主函数也可以被重载。argument,主函数的参数用“ ”空格隔开。主函数的使用。
有意思的代码:
class MainDemo {
public static void main(String[] args)//new String[]{
String[] arr = {"hah","hhe","heihei","xixi","hiahia"};
MainTest.main(arr);
}
}
class MainTest{
public static void main(String[] args)
{
for(int x=0; x<args.length; x++)
System.out.println(args[x]);
}
}//一个java文件可以有两个main函数,而且相互之间可以调用,编译后在运行时指定类名即可,还可以相互调用。
什么时候使用静态:
要从两方面下手,当对象有共享数据时定义静态变量。当功能内部没有访问到非静态方法时可以定义静态方法。每一个应用程序都有共性内容,可以将这些功能进行抽取,独立封装,以便复用。
静态的应用:
工具类ArrayTool:getMax();getMin();swap();printArr();selectsort(); 工具类中的方法都是静态的,所以创建工具类对象没意义,这时可以将工具类的构造函数私有化,不让调用者建立对象,体现了代码健壮性
帮助文档制作:
以后重要的代码都要制作帮助文档练手;java的说明书通过注释文档来制作。
这是描述类:
/** 这是一个对数组操作的工具类,该类中提供了最值获取,排序
@author 张三
@version 1.1
*/
接下来描述功能,记住,凡是public修饰符的功能都用文档描述,因为都可以被文档注释工具获取,
/** @param (代表参数)arr代表接受一个arr的数组 @return 会返回最大值什么的*/
具体的特殊字符可以翻阅API,eclipse可以很快生成
Javadoc.exe(文档编译工具)
javadoc -d c:\ -author -version (表示要在c盘的根目录生成帮助文档,附带作者和版本号。
注意:被注释的类必须是public的权限 )
一个类中的默认构造函数的权限跟所属的类的变化而变化,不写就是默认的,空参的不是默认的
静态代码块(StaticCodeDemo):
格式:static{},特点:随着类的加载而执行,只执行一次;用于给类进行初始化,优于主函数
学习静态代码块要注意各个部分的执行顺序(代码块);
对象初始化过程在内存中是怎么样的?
1、默认初始化(成员变量加默认值)。
2、显式初始化(成员变量被赋值)
3、构造代码块执行。
4、构造函数初始化。
设计模式:
其实是从建筑学学习得来的,解决问题最有效的办法,23种通用模式。
单例设计模式:解决一个类在内存中只存在一个对象(保证对象唯一性)。
想要保证对象唯一性:
1、为了避免其他程序过多建立该类对象,先控制,禁止其他程序建立对象 。
2、还为了让其他程序访问到该类对象,只好在本类中自定义一个对象。
3、为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三部怎么用代码体现:
1、将构造函数私有化。
2、在类中创建本类对象。
3、提供一个方法可以获取该对象(不能new对象,所以方法只能是Static,只有get没有set)。
饿汉式(先创建对象),
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){
synchronized(Single.class){
if(s==null)
s = new Single();
}
}
return s;
}
}
懒汉式可能会出现对象不唯一(a程序调用时判断为空时将要建立对象,cpu切换到另一个b调用时判断为null也要建立对象,
当cpu又切换到a时,又建立一个对象,不安全)。
解决懒汉式不安全的方法可以加同步锁(synchronized)但是低效。也可以用多线程解决,随后解决。
一个对象的初始化顺序:
先加载静态代码块(没有被加载过)--->构造代码块------>父类的构造函数----->本类构造函数---->类的属性加载进堆内存
Person p = new Person("zhangsan",20);
该句话都做了什么事情?
1,因为new用到了Person.class.所以类加载器会先找到Person.class文件并加载到内存中。
2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3,在堆内存中开辟空间,分配内存地址。
4,在堆内存中建立对象的特有属性。并进行默认初始化。
5,对属性进行显示初始化。
6,对对象进行构造代码块初始化。
7,对对象进行对应的构造函数初始化。
8,将内存地址付给栈内存中的p变量。
-----------------------------------------------------------------
继承:
特点:
1、提高了代码的复用性。
2、让类与类之间产生关系,有了这个关系才有了多态 的特性。
注意:不要为了获取其他类的功能,简化代码才继承,一定要有继成 关系,所属关系是 is a;(不能为玩ipad管人家叫爹)。
3、Java语言中只支持单继承(有别于C语言)。
因为多继承容易带来安全隐患(父类多了, 功能相同的话,就会出现调用不确定性)。
ps:接口可以实现多继承
4、Java支持多层继承,object是每个类的超类,实现树形结构。
类与类之间的关系:
聚集:has a .
集合:结合更紧密,例如身体中的一部分(手、肺)。不一定是继承
聚合:一个球队有很多球员的关系。子父类中变量的特点:
加载子class文件的时候,先加载父类class文件。
成员变量与局部变量的不同:1.作用域不同,成员变量在整个类中都有效,而局部变量只在离他最近的{}中有效;2,存储位置不同,成员变量位于堆内存,局部变量位于栈内存。
不同点 |
成员变量 |
局部变量 |
作用域 |
整个类中有效 |
离它最近的一对{ }内有效 |
内存中的位置 |
堆内存 |
栈内存 |
this与super:
1、如果子类出现非私有的同名变量时,子类要访问本类中的变量用this,子类要访问父类中同名变量,用super。
2、This和super的用法几乎一样。this代表本类对象的引用。super代表父类对象的引用。
覆盖:当子类继承了父类,沿袭了父类的功能,到子类中。但是子类虽具备了父类的功能,但是功能的内容却不一致,这时没必要定义新功能,而是使用覆盖,既保存了父类功能的定义,也实现了子类特有的方法。
(例如手机功能不断的发展,来电显示),在覆盖的同时又想保存父类的方法可以用super.show();
注意事项:
1、子类的方法的权限必须大于或等于父类才能覆盖,不然编译失败。
2、静态只能覆盖静态。
3、子父类方法要一模一样。
子父类中构造函数的特点:
new子类对象时,先加载父类构造函数,然后加载子类的, 原因在于子类的构造函数中默认的有隐式的super();来调用父类的构造函数。 子类中所有构造函数的第一行都是空参的super(); 为什么子类一定要访问父类的构造函数:因为父类中的数据可以直接获取,所以子类建立对象时,需要首先查看父类是如何对这些数据进行初始化的,所以子类初始化时,要先访问以下父类的构造函数。 如果要访问父类特殊的构造函数,可以通过手动定义super语句的方式来获取。注意:super();同样要放在构造函数第一行;
结论:子类中的所有构造函数,默认都会访问父类的空参的构造函数。因此,子类 的构造函数第一行都有一句隐式的 super()。
当父类没有空参的构造函数时,子类 必须手动通过super语句形式来访问父类中的构造函数。
当然,子类的构造函数第一 行也可以手动指定this语句来访问本类中的构造函数。 子类中至少有一个构造函 数会访问父类中的构造函数。
final 关键字:可以修饰类、变量、函数。
特点:
1、被final修饰的类不可以被继承。
2、被final修饰的方法不能被覆盖。
3、被final修饰的变量是常量(成员和局部都可以被修饰)。
什么时候用final?
1、当描述一些事物时,一些数值出现值是固定的,不需要被改 变,名称全部用大写字母表示,如果多个单词组成,单词间通过下划线连接。
2、 Public static final (全局常量,java中有黑多这样的常量)
3、 内部类定义在类中的局部位置上时,只能访问该部分被final修饰的局部常量。
抽象类(abstract):
当多个类中出现相同功能,但是功能主体不同,这时可以向上抽取。这时值抽 取功能的定义,而不抽取功能主体。
特点:
1、抽象方法一定在抽象类中。
2、抽象方法和抽象类,一定被abstract修饰。
3、抽象类不可以通过new建立对象,因为调用抽象方法没意义(不可实例 化)、可以有构造函数,用于继承,也可以有静态方法。
4、抽象方法要被调用,必须被子类覆盖所有抽象方法后,建立子类对象用。
如果子类没有覆盖完父类的抽象方法,那子类还是抽象类。
5、抽象可以强迫子类去实现某些功能。
比如老板提出需求,没有说明怎么实现,就是没有方法主体
练习:AbstractText.java
练习:获取一段程序运行的时间,lang 包中 system 类中public static long ——currentTimeMillis();
abstract class GetTime
{
public final void getTime()
{
long start = System.currentTimeMillis();
runcode();
long end = System.currentTimeMillis();
System.out.println("毫秒:"+(end-start));
}
public abstract void runcode();
}
class SubTime extends GetTime{
public void runcode(){
for(int x=0; x<4000; x++){System.out.print(x);}}}class TemplateDemo{public static void main(String[] args) {//GetTime gt = new GetTime();SubTime gt = new SubTime();gt.getTime();}}
模板方法模式:
在定义功能时。功能的一部分是确定的,一部分是不确定的,而确定的 部分在使用不确定的部分,那么就将不确定的部分暴露出去(不一定抽象),交给子类 去完成,确定的部分final(不一定)。
一个方法善于分拆为多个方法。
什么是模板:类似于现实中的各种模板,例如月饼,模子的花边,字是相同的, 月饼的馅却是不确定的。
接口(interface):
初期理解为特殊的抽象类,当抽象方法全是抽象是,可以定义为接口。
接口定义格式特点:
1、接口常见定义:常量(全局常量)、抽象方法
2、接口中的成员都有固定的修饰符:常量:public static final 方法:public abstract
虽然写的时候可以不加public 等等,不过不建议省略。
类与类之间是继承关系,类与接口是实现关系。Implements 关键字。父类中有非抽象 内容子类可以直接拿来用,而接口全是抽象,需要全部覆盖才能实现功能。
—— Interface编译后也是class文件。
—— 接口可以多实现,是对继承只能单继承的补充。可以同时继承还能实现接口, —— 顺序:先继承后实现接口。
—— 接口可以继承接口。
—— java只在接口与接口之间有多继承。
接口的特点:
1、接口是对外暴露的规则。
2、接口是程序的扩展。
3、接口可以用来多实现。
4、接口与接口之间可以多继承,用,隔开
5、类与接口是实现,而且一个类在继承的同时实现多个接口。降低了耦合性(讲好规则之后,可以分拆,同时开工,模块式开发)
interface Inter
{
public static final int NUM = 3;
public abstract void show();
}
interface InterA
{
public abstract void show();
}
class Demo
{
public void function(){}
}
class Test extends Demo implements Inter,InterA
{
public void show(){}
}
interface A{
void methodA();
}
interface B //extends A{
void methodB();
}
interface C extends B,A{
void methodC();
}
class D implements C{
public void methodA(){}
public void methodC(){}
public void methodB(){}
}
class InterfaceDemo
{
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.NUM);
System.out.println(Test.NUM);
System.out.println(Inter.NUM);}}-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
多态:
某种事物具有多种表现形式。人有男人和女人。覆盖和重载都是多态的表现。
多态的体现:父类的引用指向了自己的子类对象。父类的引用也可以接受子类的对象。提到了反射。
多态的前提:必须是类与类之间有关系,要么继承,要么实现。
通常还有一个前提:存在覆盖。
多态的好处:多态的出现,大大提高了程序的扩展性。
多态的弊端:只能使用父类的引用,访问父类中的成员。 Animal a = new cat();// 类型转换,向上转型,自动完成。
Cat c = (cat)a; // 想要调用猫的特有方法时,可以用向下转型:强制将父类的应用,转成子类对象。
给我一只动物,给个猫给个狗也行。要是要个猫,给个狗就不行。千万不要将父类对象转换成子类类型。
我们能转换的是:父类引用指向子类对象时,该类型可以被引用,可以被强制转换,多态自始至终是子类对象的变化。
经典例子:
父亲,儿子都是教师,父亲教工商管理,儿子教java的功能,儿子有特定的方法,看电影。毕姥爷,毕老师,胡子,大衣、、
Classcastexception类型转换异常。实例对象.instanceof(类);用来判断对象的属性。
多态的出现代码中的特点(多态使用的注意事项):
多态非静态成员函数
在编译时期:参阅引用型变量所属的类中是否有调用方法。如果有,编译通过;如果没有则失败。
在运行时期:参阅所属的类中是否有调用的方法。
简单总结就是:编译看左边,运行看右边。
面试会遇到的问题:
多态中,成员变量的特点:无论编译还是运行,都参考左边(引用型变量所属的类)。
多态中,静态成员函数的特点:同上。因为先加载,不属于对象。
class Fu{
static int num = 5;
void method1(){
System.out.println("fu method_1");
}
void method2(){
System.out.println("fu method_2");
}
static void method4(){
System.out.println("fu method_4");
}
}
class Zi extends Fu{
static int num = 8;
void method1(){
System.out.println("zi method_1");
}
void method3(){
System.out.println("zi method_3");
}
static void method4(){
System.out.println("zi method_4");
}
}
class DuoTaiDemo4{
public static void main(String[] args)
{Fu f = new Zi(); System.out.println(f.num);//打印室父类的num = 5 f.method1(); //f.method3();//编译报错 f.method4();//父类方法没有被覆盖 f.method2(); System.out.println( "------------------------"); Zi z = new Zi(); z.method4();//静态方法,没有覆盖,用eclipse时,用对象调用时会警告
z.method1(); z.method2(); z.method3();
}/*显示结果 * 5zi method_1fu method_4fu method_2------------------------zi method_4zi method_1fu method_2zi method_3*/}
多态的主板示例:
PCI接口,主板、网卡、声卡、debug卡
接口开发模式,从第collection col = new ArrayList();//接口的引用指向子类对象。提高程序健壮性和扩展性
多态的扩展示例:
数据库的操作:
1)连接数据库 (JDBC Hibernate框架连接)
2)操作数据库(c r u d )
3)关闭数据库连接
object:
超类,包含所有对象都有的功能。Java认为所有对象都具备比较性,equals方法比较的是哈希值。
让类可以比较的话不用再定义新的功能,可以直接覆盖超类的方法。
class Demo //extends Object
{
private int num;
Demo(int num)
{
this.num = num;
}
public boolean equals(Object obj)//Object obj = new Demo();
{
if(!(obj instanceof Demo))
return false;
Demo d = (Demo)obj;
return this.num == d.num;
}
/*
public boolean compare(Demo d)
{
return this.num==d.num;
}
*/
public String toString()
{
return "demo:"+num;
}
}
class Person
{
}
class ObjectDemo
{
public static void main(String[] args)
{
Demo d1 = new Demo(4);
System.out.println(d1);//输出语句打印对象时,会自动调用对象的toString方法。打印对象的字符串表现形式。
Demo d2 = new Demo(7);
System.out.println(d2.toString());
//Demo d2 = new Demo(5);
//Class c = d1.getClass();
}
}
内部类:
内部类的访问规则:
1、内部类可以访问外部类的成员(因为outer.this.成员变量),包括private的。
2、外部类要访问内部类,要先建立内部类对象(格式: 外部类.内部类 名字 = new 外部类.内部类();)。
3、内部类在外部类成员位置上时可以被private修饰,用 来封装。
4、内部类被static修饰后跟静态用法一样(不能访问非 静态变量、因为没有super和this)
5、当内部类中的定义了静态成员,该内部类必须是static
6、当外部类中的静态方法访问内部类时,内部类也必须 是static的
7、内部类中要访问局部变量,需要被声明为final
内部类什么时候用:
当描述事物时,事物的内部还有事物,该事物用内部类来描述(比如人类,人内有各种器官),因为内部类在使用外部类的内容
内部类定义在局部时:
1、不能被成员修饰符修饰。
2、可以直接访问外部类成员,因为还持有外部类引用,但是不可以访问局部变量,只能访问final修饰的局部类。
3、在其他的外部类中部内new出内部类
匿名内部类:
1、匿名内部类其实是内部类的简写格式。
2、定义匿名内部类的前提:内部类必须是继承一个类或者实现接口
3、匿名内部类格式:
new 父类或者接口(){定义子类内容}
4、匿名内部类就是匿名的子类对象,而且这个对象有点胖。可以理解为 带内容的对象。
5、匿名对象只能调用一次。
6、匿名内部类中的方法,最好不要超过三个。