------- android培训、java培训、期待与您交流! ----------
面向对象:
面向对象是相对面向过程而言的;
面向过程强调的是功能行为,面向对象是将功能封装进对象,强调具备了功能的对象,面向对象是基于面向过程的.
面向对象三个特征:
封装(Encapsulation):指隐藏对象的属性和实现细节,及对外提供公共访问方式(public修饰的类成员),
好处:将变化隔离(可以扩展,不会影响已存在的程序),便于使用,提高重用性,提高安全性;
原则:将不需要对外提供的内容都隐藏起来;把属性都隐藏,提供公共方法对其访问,之所以提供访问方式因为可以在
访问方式中加入逻辑判断等语句,对访问的数据进行操作,提高了代码健壮性;
体现形式:权限的设置private,public,默认
继承(extends):必须是类与类之间有所属关系才可以继承
作用:1,提高了代码的复用性;
2,让类与类之间产生了关系,有了这个关系才有了多态的特性,Java语言中只支持单继承,不支持多继承,因为多继承容易带来安全隐患,当多个父类中定义了相同功能,当内容不同时不能确定要执行那个功能;但是Java保留这种机制,可以实现多个接口;
Java支持多层继承,也就是一个继承体系;如何使用一个继承体系,简单一句话:查阅父类功能,创建子类对象使用功能;
1,变量:如果子类中出现非私有的同名成员变量时,子类访问本类中的变量用this.变量名,子类要访问父类中同名变量使用super.变量名;
2,函数:当子类出现和父类一模一样的函数时,当子类对象调用该函数时,会运行子类自己定义的函数,如同父类的函数被覆盖了一样,即重写;
3,构造函数:子类所有的构造函数第一行默认有一句隐式super(),当创建子类对象时,父类的构造函数(无参的那个)也会被执行;子类一定要访问父类中构造函数,因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问一下父类的构造函数,如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式指定;当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,但是,子类中至少有一个构造函数会访问父类的构造函数;
覆盖(重写):父类中的成员不能是private权限,因为子类看不见父类的private成员;
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖否则编译失败;
2,静态只能覆盖静态;
final(关键字):一个修饰符,可以修饰类,函数,变量;
1,被final修饰的类不能被继承,为了避免被继承后功能被子类重写;
2,被final修饰的方法不能被重写;
3,被final修饰的变量是一个常亮只能被赋值一次,既可以修饰成员变量,也可以修饰局部变量;
4,内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量;
abstract(抽象):一个修饰符,可以修饰类,函数;作用,不让类创建对象,抽象类中可以不定义抽象方法;
1,抽象方法一定在抽象类中;
2,抽象方法和抽象类都必须被abstract关键字修饰;
3,抽象类不可以用new创建对象,因为调用抽象方法没意义;
4,抽象类中的抽象方法要被使用,必须由子类复写所有的抽象方法,创建子类对象调用;
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类;
interface(接口):用于定义接口,接口用于功能扩展的,格式 interface 接口名{}
接口中常见定义:常量,抽象方法;
接口中成员都有固定修饰符:常量:public static final;方法:public abstract;
接口中的成员都是public的,上面的固定修饰符都可以省略,编译器默认加上;
接口不可以创建对象,因为有抽象方法;需要被子类实现(implements),子类对接口中抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类;
接口可以被类多实现,也是对多继承不支持的转换:class C implements A,B{}
接口之间也存在继承关系:interfaceA extends B,C{}//接口的继承支持多继承,保证BC中不存在同名不同返回值的方法;
类之间的关系除了继承还有聚合,组合:
聚合:事物A由事物B等组成,但是事物A缺失了组成元素中某一个事物B不会影响事物A的自身属性和功能;
组合:事物A由事物B等组成,但是一旦事物A缺失了组成元素
多态:
1,多态的体现:父类的应用指向了自己的子类对象,父类的应用也可以接收自己的子类对象;
2,多态的前提:必须是类与类之间有关系,要么继承,要么实现;通常还有一个前提,存在覆盖;
3,多态的好处:多态出现大大提高了程序的扩展性;
弊端:提高了扩展性,但是只能使用父类的引用访问父类中成员
4,多态的应用:接口降低了程序的耦合性,使多态扩展性提高
5,多态成员函数使用特点:
在编译时期,参阅引用类型变量所属的类中是否有调用的方法;如果有编译通过,如果没有编译失败;在运行时期,参阅对象所属类中是否有调用的方法;简单总结就是,成员函数在多态调用时,编译看左边,运行看右边;
在多态中成员变量:无论在编译时,还是运行时都参阅左边(引用型变量所属的类);
在多态中静态成员函数的特点:无论在编译和运行时,都参阅左边;
Animal a = new Cat();//类型提升,向上转型
Cat c = (Cat)a;//强制将父类的应用,转成子类类型,向下转型
Animal a = newAnimal();
Cat c = (Cat)a;//这种转换是错误的,因为不能将父类对象转成子类类型
注:父类应用指向了自己子类的对象时,该应用可以被提升,也可以被强制转换,多态自始至终都是子类对象在做变化。
类和对象的关系:
类是对现实生活中事物的描述,映射到java中,描述就是class定义的类;
匿名对象:是对象的简化形式,有两种使用情况,当对象方法仅进行一次调用时,匿名对象可以作为实际参数进行传递;对象是这类事物,实实存在的个体,具体的对象就是对应java在堆内存中创建的对象;
构造函数:函数名和类名相同,不用定义返回值类型,不可以写return语句;
作用:给对象初始化,建立就会调用与之对应的构造函数;
当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数;
构建函数只在创建对象时调用一次;
构造代码块:给对象进行初始化,定义的是不同对象共性问题,对象一建立就执行,而且优先于构造函数执行
静态代码块:static{执行语句},随着类的加载而执行,只执行一次,用于给类进行初始化
public classStaticDemo{
public staticvoid main(String[] args){
newStaticCode();
newStaticCode();
}//执行结果:aStaticCode StaticCode
}
class StaticCode{
static{
System.out.print('a'+"");
}//只有用到类里面的内容是才会执行静态代码块
publicStaticCode(){
System.out.print("StaticCode");
}}
和构造函数区别:构造代码块是给所有的对象进行一次初始化,而构造函数时给对应的对象初始化
this:就代表本类的对象,this代表它所在函数所属对象的引用;简单说,哪个对象调用this所在的函数,this就代表哪个对象;
当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象;
this():语句用于构造函数间调用,但是对 this 的调用必须是构造函数中的第一个语句;
static:静态关键字;用于修饰成员(成员变量和成员函数),被修饰的成员放在共享区(方法去/数据区)
被修饰后的成员具备的特点:随着类的加载而加载,静态会随着类的消失而消失,非静态成员随着对象的消失而消失;
优先于对象存在;被所有的对象所共享;可以直接被类名调用,类名.成员;
static Stringcountry="CN";//这个country成员变量无论你创建多少个对象,在内存中都只有一个
用法:是一个修饰符,用于修饰成员只能修饰成员,被static修饰的成员在内存中只被分配一次空间,这个空间可以被多个对象实例使用;
实例变量(非static)和类变量(static)的区别:
1,存放位置:类变量存放在方法区中,实例变量随着对象的创建而存在于堆内存中;
2,生命周期:类变量生命周期最长,随着类的消失而消失,实例变量生命周期随着对象的消失而消失;
静态的使用注意事项:
1,静态方法只能访问静态成员,非静态方法既可以访问静态也可访问非静态;
class Person{
privateString name;
privateint age;
publicstatic void show(){
System.out.println(name);//报错:无法从静态上下文中引用非静态 变量 name
}
}
2,静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法中不可以出现this,也就是说静态方法调用this还没有对应的对象存在呢;
3,主函数是静态的,是一个特殊的函数,作为程序的入口,可以被jvm调用,主函数是固定格式的为了jvm识别;
Person p = new Person("zhangsan",32);
1,因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中;
2,执行类中的static代码块,如果有的话,给Person.class类进行初始化;
3,在堆内存中开辟空间,分配内存地址;
4,在堆内存中建立对象的特有属性,并进行默认初始化;
5,对属性进行显示初始化;
6,对对象进行构造代码块初始化;
7,对对象进行对应的构造函数初始化;
8,将内存地址付给栈内存中的p变量;
设计模式:解决某一类问题最行之有效的方法
java中有23中设计模式:
单例设计模式:解决一个类在内存中只有一个对象存在;定义单例模式一般使用饿汉式;
想要保证对象唯一:
1,为了避免其他程序过多创建该类对象,先禁止其他程序创建该类对象;
2,还为了其他程序可以访问该类对象,只好在本类中自定义一个对象;
3,为了方便其他程序对自定义的对象的访问,可以对外提供一些访问方法;
classSingle{//饿汉式:Single类一进内存,就已经创建了对象
privateSingle(){};//1
Singles = new Single();//2
publicstatic Single getInstance(){//3
returns;
}
}
classSingle{//懒汉式:Single类进内存,对象还没有存在,只有调用了getInstance方法时才创建对象;
privateSingle(){};//1
Singles = null;
publicstatic synchronized Single getInstance(){//3;synchronized锁保证唯一性但是降低了运行效率
if(s== null)//进入if后执行new前可能被CPU暂停执行下一个程序(这个程序创建了Single对象),再回来继续执行new这个时候堆中就有两个Single对象了
s= new Single();//2
returns;
}
}
模板方法设计模式:在定义功能室,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时候就将不确定的部分暴露出去,由该类的子类去完成
例子:abstractclass GetTime{
publicvoid getTime(){
longstart = System.currentTimeMillis();
runcode();
longend = System.currentTimeMillis();
System.out.println(end-start);
}
publicabstract void runcode();//由于具体要运行代码不确定,这个不确定也可以由默认的实现,根据开发需求而定
}
练习1:this的作用练习
class Person{
private String name;
private int age;
Person(int age){
this.age = age;
}
Person(String name,int age){
this(age);
this.name = name;
//this.age = age;
}
public boolean compareAge(Personp){
return this.age ==p.age;
}
}
class PersonDemo1{
public static void main(String[]args){
Person p1 = newPerson(23);
Person p2 = newPerson(34);
System.out.println(p1.compareAge(p2));
}
}
练习2:抽象类练习
/*
假如我们在开发一个系统是需要对员工进行建模,员工包含3个属性,姓名、工号、以及工资,除了
含有员工属性外,另外还有一个奖金属性,请使用继承的思想设计出员工类和经理类,要求类中提供必要
的方法进行属性访问
*/
abstract class Employee{
private String name;
private String id;
private double pay;
Employee(String name,Stringid,double pay){
this.name = name;
this.id = id;
this.pay = pay;
}
public abstract void work();
}
class Pro extends Employee{
Pro(String name,String id,doublepay){
super(name,id,pay);
}
public void work(){
System.out.println("Prowork");
}
}
class Manager extends Employee{
private int bonus;
Manager(String name,Stringid,double pay,int bonus){
super(name,id,pay);
this.bonus = bonus;
}
public void work(){
System.out.println("Managerwork");
}
}