=============类和对象 ====================== 类:类是同一类事物的总称。 对象:现实世界中实实在在存在的事物。 类和对象的关系:类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体称为类。如鸟类有鸵鸟、大雁、麻雀等。鸵鸟、大雁、麻雀被称为鸟类的实体,即对象。 面向对象:对象所共有的功能和属性进行抽像,成为了类。客观事物在人脑中的主观反映。在程序里类是创建对象的模板。 面向对象程序设计的特点:封装性、继承性、多态性。 类成员:成员变量(属性)和成员方法(行为)。 定义成员方法的格式:权限修饰符 返回值类型 方法名(参数类型 参数名) {方法体 return返回值} 成员方法需要返回值时使用关键字 return java中的对象 :对现实对象的抽象(获得有用的,舍弃没用的)。 存储空间中的一块数据区域,用于存数据。如:人(nama sex age) 属性:实例变量(定义在类以内,方法之外) 1.默认的初值 2.实例变量的使用范围至少是类以内 3.实例变量调用必须有对象,实例变量和局部变量重名,局部优先。 例: public class Test{ public static void main(String[] args){ //新建对象stu;stu存的是新建对象stu的地址。stu的专业术语:引用/对象变量/引用变量/实例变量 Student stu=new Student(); stu.name="tom"; //给对象stu的name属性赋值。 }} class Student{ //用类声明的数据(str)为引用类型,如:Student str; //实例变量:定义在方法之外,类以内的,没有static修饰的变量 //实例变量会有一个默认的初始值。初始值与变量定义时的类型有关。 //实例变量(成员变量)--->属性。可通过新建对象的引用来访问类的实例变量。如,stu.name; String name; int age; String sex; } 实例变量和局部变量的区别: 1,位置:局部变量定义在方法里面。实例变量定义在类以内方法之外。 2,使用的范围:局部变量只能在定义他的方法里面使用,直接调用变量名就可以了。 实例变量至少可以在定义他的整个类内使用,使用时必须用对象去调用。只有跟对象一起实例变量才有意义。 3,局部变量使用之前必须初始化。实例变量不需要赋初值,系统会给默认的初值。 4,局部变量在同一方法里不能重名。局部变量和实例变量可以重名,在方法里采用就近原则。 =================方法:============= 包括: 方法: 做什么:方法的定义 修饰符 返回类型 方法名(参数列表) 异常 怎么做:方法的实现 {******} 修饰符(如:public) 返回类型(如:int) 方法名/函数名(参数表--形参) 如: public void eat(String fish){ //eat(),吃的功能。 //怎么做. } 使用实例方法时也需要用对象去调用。如:stu.eat("fish"); ======构造方法====== 功能:创建其所属类型的一个新的对象。(构造方法无返回值类型) 语法格式: < modifiers修饰符> <class_name类名>([< argu_list>]) { [< statements>] 方法体 } 举例: –class Person { int age; Person() { age = 18; } Person(inti) { age = i; } void setAge(inti) { age = i; } –} Java语言中,每个类都至少有一个构造方法; 如果类的定义者没有显式的定义任何构造方法,系统将自动提供一个默认的构造方法: –默认构造方法没有参数 –默认构造方法没有方法体 Java类中,一旦类的定义者显式定义了一个或多个构造方法,系统将不在提供默认的构造方法;每个子类的构造方法里都有一个父类的默认构造方法,即super(),注意:前提是父类没有显示的构造方法,当父类有一个或多个显示构造方法时,子类的构造方法要想调用,必须在方法体第一行加上 super(参数类型)。 方法重载(overloading):编译时多态。 在一个类的内部,方法名相同形参数不同的方法,对返回类型不要求,这种现象称之为重载; 编译器会自动选择使用的方法。体现了一个编译时多态。 好处:对使用者屏蔽因为参数不同造成方法间的差异。 找方法时如果没有合适的,采取自动向上扩展原则。 调用时形参之间的区别一定要明确。 1. 形参的个数不同 2. 形参的类型不同 3. 形参的顺序不同 4. 形参的名字相同 方法覆盖(override):运行时多态。 1,发生在父类和子类之间 2,方法名相同,参数相同,返回类型相同 3,子类方法的访问权限不能更严格,只能等于或更加宽松。 构造方法: 1,没有返回类型,方法名必须和类同名。 2,构造方法不能手动调用,它只用在创建对象在时候,只出现在new之后。 只要构造方法被调用运行,就一定有对象产生。 3,在一个对象的生命周期里,构造方法只能被调用一次。 4,类写好后一定有构造方法, 如果程序没有显示的提供构造方法,JVM会提供一个默认的构造方法,public classname(){} 如果程序显示提供,系统不再提供默认的 5,同一个类的多个构造方法一定重载。 6,创建对象的同时构造方法的代码块里还可以写需要运行的代码,还可以给属性(实例变量)赋值, 引用类型的属性赋值就是用new创建对象,然后调用构造方法。如:Student stu=new Student(); 用new创建对象时JVM做的三件事: 如:Student stu=new Student(); 1,申请空间;(把值放到空间里,再把空间的地址给引用变量。)----创建父类对象 2,初始化实例变量;没显示声明值的话就用默认值。 3,执行构造方法, 因为实例变量在创建对象的过程中被初始化,所以使用实例变量前必须创建对象(要用对象去调用),否则实例变量根本不存在 =====关键字:this======= 1,在普通方法里,指代当前对象引用(哪个对象调用该方法,this就指向该对象) 2,this不能出现在静态方法里。 3,在构造方法里,this用来指代本类的其他构造方法。在本类构造方法之间互相调用。如:this(形参); 使用时放在构造方法里的第一行。 4,不能写成死循环(不能递归调用) =====关键字:super======= (和this的用法类似) 1,调用父类的构造方法,在子类调用父类的构造方法必须出现在第一句,构造方法第一句可能出现的三种情况(调用父类的构造方法看子类构造方法的第一句)①super();②super(参数)注意传递的参数一定是实体,有值的。③this(),先在本类的构造方法间调用,再看调用那个构造方法的第一句是什么 2,super访问父类的变量和方法,及super代表父类的对象,super.name;super.setName(); 注意:this 和super关键字不能同时存在在方法体中。 ======参数传递======== 1,参数相当于局部变量 2,参数传递相当于赋值语句 3,基本类型数据传递的是本身的值,引用类型数据传递的是引用xx(Animal animal)(地址,对象变量本身的值) 面向对象的三大特性: 一,封装(Encapsulation):一个系统以合理的粒度出现。 定义:封装就是将客户端不应看到的信息包裹起来。使内部执行对外部来看不一种不透明的、是一个黑箱,客户端不 需要内部资源就能达到他的目的。(封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象 计算始于这个基本概 念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。) 1.事物的内部实现细节隐藏起来 2.对外提供一致的公共的接口――间接访问隐藏数据 3.可维护性 访问控制修饰符:public(公开的),protected(受保护的,1,本包内可见;2,其他包的子类可见) default(默认,本包内可见),private(私有的,类内部可见) 访问控制修饰符 (可以范围) (可修饰)下面的类(指外部类) private 本类 方法,属性 default 本包 类,方法,属性 protected 本包+子类 方法,属性 public 到处可见 类,方法,属性 1,属性:隐藏所有属性,用private。隐藏后属性只能在类以内访问 。程序可以根据需要提供get和set 2,方法(函数):该公开的公开,该私有的就私有。(视情况而定) 3,公开方法的功能,隐藏方法的实现细节。 二,继承(inheritance):抽象出不变性。 从一般到特殊的关系,可以设计成继承 特点:共性写在父类里面,特性写在子类 所有类的总父类是Object (Object是类的祖先) 父类里写的是共性,子类里写的是特性。 父类中用private修饰的属性和方法不能被子类继承; 但是父类里的属性子类都有,如果子类有特殊属性的话,就要在子类里定义 且在创建该子类对象的时候初始化属性(包括父类所有属性和该子类所有属性); 什么样的功能和属性可以继承到子类? 对于父类里的属性和方法,子类有权访问的,我们称为可以继承; 用new创建子类对象,JVM执行的过程:Dog d=new Dog(); 为d申请空间。class Dog extends Animal{} (1)申请空间;(把值放到空间里,再把空间的地址给引用变量。) (2)看本类构造方法的第一句 (3)默认的创建父类对象: 执行顺序:子类(2)---> 父类(2-->3-->4-->5)---> 子类(4-->5), 新建一个对象空间只申请一次(该空间存放所有父类和子类)。) (4)初始化本类的实例变量(该类的所有属性); (5)执行本类的构造方法,(构造方法只会在创建一个对象的时候被执行一次) (创建是先执行父类的构造方法,在执行子类的构造方法,访问时先访问子类自己的特殊属性和方法再访问父类的属 性和方法) 用super调用父类被子类覆盖的普通方法和遮盖的属性 , 指代的是在创建子类对象过程中,由JVM自动创建的那个父类,如:super.方法名()/属性 用super调用父类的构造方法;必须出现在子类构造方法的第一句。如:super(形参); 1,在子类的构造方法里如果没有指明调用哪一个父类的构造方法(就是子类中没有super(形参)语句;), JVM会默认调用父类的无参构造方法,跟本类构造方法的形参没有关系。 2,显示的写super,JVM会根据参数调用相应的父类构造方法。 3,有this(形参),在本类的构造方法之间调用,看被调用的那个构造方法的第一行。 三,多态(polymorphism):多态只有方法多态,没有属性多态。 用父类类型屏蔽子类之间的差异 所有的子类对象都可以当父类对象来用,一个父类型的引用可能指向的是一个子类对象, 如:把狗(对象)看作动物(类型)。Animal a=new Dog(); 编译看前面,运行看后面。 (编译时类型) (运行时类型) 1,运行时对象不会改变(对象是客观存在的),如:狗这个对象的属性和方法是不会改变的。 2,对一个引用,只能调用编译时类型里的已知方法。 如:编译器知道动物里已有的属性和方法,但不知道狗的属性和方法。 3,运行时会根据运行时类型自动寻找覆盖过的方法运行。 引用 instanceof 类名 instanceof是Java的一个二元操作符,和==,>,<是同一类东西。 由于它是由字母组成的,所以也是Java的保留关键字。 它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。 //结果为boolean值, 引用所指向的对象和类名类型是否一致(对象是否属于类名类型) 类型的转换:转换编译时类型 Sub su= (Sub) s; 子类型的引用向父类型转换时,不需要强转 父类型的引用向子类型转换时,需要强转 Animal a=new Cat(); Dog d=(Dog)a; // 类型转换异常 引用 instanceof 类名 -----> boolean 引用所指向的对象和类名所代表的类型是否一致 a instanceof Animal -----> true a instanceof Cat----------> true a instanceof Dog----------->false Employee e=new Manager(); e instanceof Employee ------>true e instanceof Manager------> true 属性没有多态,属性只看编译时类型 编写程序的顺序: class 类名{ private属性(有什么) 无参的构造方法(public类名(){}) 有参的构造方法(作用:给属性赋值) set和get(设置和获得属性) 业务方法(做什么) } 一,修饰符:static static变量:如:static int index=2; 类的所有对象共同拥有的一个属性;可以用类名直接访问,又称为类变量, 类的所有对象共同拥有的一个变量;类第一次被加载时会初始化静态变量 (也就是会先执行static修饰的变量); 跟类创建了多少对象无关;任何对象对静态变量做的修改,其他对象看到的是修改后的值。 可以用作计数器,记录类创建对象的个数, static变量在类加载的时候只会被初始化一次, static方法:如:public static void teach(){} 可以用类名直接去调用,不需要对象所以不能直接访问(在没有对象的情况下)实例变量, 在静态方法里不能出现this和super,类的所有对象共同拥有的一个方法;跟类创建了多少 对象无关。 在继承里,父类的静态方法只能被子类的静态方法覆盖,且覆盖以后没有多态 (访问的是父类的静态方法); static初始化块:如:class Teacher(){ static int index=4; static{ //static初始化块 ......... } } 静态初始化块:用static修饰类里面的一个独立的代码块,类第一次被JVM加载的时候执行,只 被执行一次。 类加载:JVM在第一次使用一个类时,会到classpath所指定的路径去找这个类所对应的字节码文件, 并读进JVM保存起来,这个过程称之为类加载,一个线程一个jvm。 二,final (最后的,最终的)final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承 final类:如:final class Animal{} 表示该类不能被继承,意味着不能改变里面的代码; 对虚拟机的正常运行有重要作用的类通常用final修饰,如:String,System,Math ...等类 final方法:如:public final void sleep(){} 该方法不能被覆盖(修改),但能被子类访问。 final变量:如:final (static) int index=4; 该变量是常量能被继承(访问); final修饰的变量就是常量,通常和static一起连用,来声明常量; final修饰引用类型数据,指的是引用(地址)不能变,但引用里的数据不受限制。 final修饰的变量,只要在初始化的过程中就可以赋值。 实例变量:声明的同时或构造方法里赋值; 静态变量:声明的同时或在静态代码块里赋值; 三,abstract abstract类:如:abstract class Animal{} 抽象类,不能创建对象(如一些父类),但是可以声明一个抽象类型的引用 (可以声明父类类型子类对象,编译时利用多态调用抽象方法)。 含有抽象方法的类一定是抽象类,但抽象类并不一定要有抽象方法; 抽象类一般是用来被继承的;子类继承自抽象类,就要实现里面的抽象方法, 如果不想让子类也是抽象类的话,必须实现父类里面所有的抽象方法。 抽象类有构造方法,有父类,也遵循单继承的规律。 abstract方法:如:public abstract void sleep(); 抽象方法,只有方法名的定义,没有实现体(只定义了能做什么,没定义怎么做),不能被调用, 用于被子类的方法覆盖或重新实现。只能放在抽象类中。 好处:允许方法的定义和实现分开。 public protected default private static final abstract 可以: public static private static public final public static final 不可以:abstract final void eat(); private abstract void eat(); static abstract void eat(); abstract不能和final,private,static连用。 四,interface:是抽象类的变体,。在接口中,所有方法都是抽象的。如:interface M{ int num=3; void eat(); } 理解为接口是一个特殊的抽象类,所以接口不能创建对象,且接口没有构造方法, 但可以声明一个接口类型的引用(m是接口类型实现类对象,如:M m=new N();) 接口存在的意义是被子类实现,如果不想让子类也抽象, 就要实现接口里面所有的抽象方法,实现过程中注意访问权限; 用 implements 关键字实现接口,如:class N implements M{ public void eat(){...} } 接口里面的常量默认都是public static final的; 接口里面的方法默认都是public abstract的。 接口本身支持多继承,继承了父接口里功能的定义,如,interface A extends B,C,D{} //A,B,C,D都是接口; 类可以同时继承一个父类和实现接口(或多个接口)。 如:class AA extends BB implements CC,DD,EE{}//AA,BB 是类,CC,DD,EE是接口; 作用:1,用接口去实现多继承,接口是对类的共性进行再次抽象,抽象出类的次要类型。 如:蜘蛛侠,拥有人和蜘蛛的属性,但主要类型是人,次要类型(接口)是蜘蛛, 因为接口是次要类型,所以在类关系里不占一个节点,不会破坏类层次关系的树状结构, 2,标准(保证弱耦合):一个接口就是一个标准(里面的属性不能改变,只定义了功能, 但没有被实现), 接口将标准的制定者,标准的实现者以及标准的使用者分离开, 降低实现者和使用者的耦合。接口是java里一种重要的降低耦合的工具; 接口可以屏蔽不同实现类的差异, 当底层的实现类更换后,不会对上层的使用者产生影响,体现在参数和返回值。 写程序时,应该先写实现者再写使用者,如:Bank.java是实现者,View.java是使用者, 但是有了接口之后,就可以用接口回调的功能; 接口回调:先定义接口,然后写使用者和实现者的顺序随便(一般是先写使用者, 后写实现者);利用参数把实现者传给使用者(即:实现者是使用者的属性), 使用者利用接口调用实现者相应的功能。 **接口和抽象类的区别1一个类可以implements多个接口,而只能extends一个抽象类 2,一个抽象类可以实现部分的方法,而接口都是抽象的方法和属性 Object是Java里所有类的直接或间接父类,Object类里面的所有功能是所有java类共有的 1,JVM调用垃圾回收器回收不用的内存(没有引用指向的对象)前运行finalize(),给JVM用的方法。 程序显示的通知JVM回收没用的内存(但不一定马上就回收):System.gc();或 Runtime.getRuntime().gc(); 2,toString()返回对象的字符串表现形式,打印对象时,虚拟机会自动调用toString获取对象的字符串表现格式, 如:System.out.println(str.toString()); ==System.out.println(str); 如果本类不提供(覆盖)toString(),那么使用的是Object类里的相应方法,打印的就是地址。 如:public String toString(){ return "....."; } 3,基本类型时“==“判断变量本身的值是否相等;引用类型时,判断的是地址是否相等。 equals判断的是对象内容是否相等。对于自己创建的类,应该覆盖Object类的equals()方法; 否则使用的是Object类里的equals()方法,比的是地址。 覆盖方法如下: /***************************************************** public boolean equals(Object o){ if(o==null) return false; if(o==this) return true; if(!(o.getClass()==this.getClass())) return false; final Student s=(Student)o; return this.name.equals(s.name) && this.age==s.age ; //比较原则; } ******************************************************/ 覆盖euqals()方法时遵循的原则: 自反性:a.quals(a); //true 对称性:a.equals(b);<==> b.equals(a); //true 传递性:a.equals(b);//true b.equals(c); //true --->则:a.equals(c); //为true 封装类(Wrapper class): OverLoading时,基本类型时采用向上匹配原则, 如果没有基本类型的话就向包装类转换,如果还没有就让这个基本类型在包装类里也采用向上匹配原则; 基本类型-转换到-->包装类 boolean----->Boolean int-------->Integer //Integer是引用类型, int-------->Ddouble //合法, 但Integer------>Double 非法 double------>Double ...... -------> ...... 任何类型----->Object 基本数据类型int可以向double自动扩展,但是包装类型之间不能自动的相互转换, 基本类型数据--->包装类型 int i=3; Integer it=new Integer(i); //手动转换;基本类型向包装类型转换。 int <----> Integer <----> String 转换时String类型必须为全数字字符串。如:"2515" 不能为:"abc265","aec"...等 String str=”123”; int it=Integer,parseInt(str);把字符串转换成数字。String str2=it+“”;把数字转化成字符串 ==内部类============ 定义在其他代码块(类体或者方法体)里的类称为内部类; 编译后每一个内部类都会有自己的独立的字节码文件, 文件名:Outer$Inner.class-->内部类也可以有父类和实现接口。也可以有抽象方法。 根本位置和修饰符的不同分为四种: 1,member inner class 成员内部类,当实例方法或变量一样理解。 1)定义的位置:类以内,方法之外,没有静态修饰符(static)。 2)本身能定义的属性和方法:只能定义非静态的属性和方法。 3)能直接访问的什么:能访问外部类的所有静态和非静态的属性或方法。 4)怎么创建对象:在外部类内的方法内:Outer.Inner inner=new Outer().new Inner(); 在外部类外的类的方法内:Outer.Inner inner=new Outer().new Inner();或 在Outer类里提供一个getInner()方法,返回内部类的对象,这样在外部类外的类的方法内也可以用该成员内部类。 2,static inner class 静态内部类(嵌套内部类),当静态方法或变量一样理解。 static只能修饰内部类,不能修饰外部类。 1)定义的位置:类以内,方法之外,有静态修饰符(static)。一般写在外部类的属性下面。 2)本身能定义的属性和方法:可以定义静态和非静态的属性或方法。 3)能直接访问的什么:只能访问外部类的静态属性和方法。 4)怎么创建对象:在外部类内的方法里: Outer.Inner inner=new Outer.Inner(); 在外部类外的类方法里: Outer.Inner inner=new Outer.Inner(); 3,local inner class 局部内部类 当局部变量一样理解。 1)定义的位置:方法里面的类,前面不能用public或static修饰。 2)本身能定义的属性和方法:只能定义非静态的属性和方法。 3)能直接访问的什么:能访问方法内用final修饰的局部变量(不能与该类内的变量名相同)。 能访问外部类的所有静态和非静态的属性或方法。 4)怎么创建对象:只能在方法内创建对象,如:Inner inner=new Inner(); 对象的作用范围只在方法内。 4,annonymous inner class 匿名内部类 如: Teacher tc=new Teacher(){ 1)没有名字的类,没有构造方法。是一个特殊的局部内部类, public void teach(){...} 可以实现一个接口, 或者一个类, } 生命周期里只能产生一个对象(tc),也就是说只能被一个对象(tc)调用, 2)除了没有名字外,看匿名内部类所在的位置,他的定义和访问将和成员内部类、静态内部类、局部内部类一样。 一般像局部内部类的定义和访问比较多。 3)当试图创建接口或者抽象类对象的时候,用匿名内部类。 表示类体的{...}紧跟在抽象实例(接口)之后,表示实现该抽象实例(接口)。 调用匿名内部类的方法只能用写类时创建的那个对象(tc)。 作用:1,不破坏访问权限的情况下,内部类可以使用外部类的私有成员变量和方法。 2,将接口公开,将实现类(实现公开的接口)作成内部类隐藏起来,强制要求使用者使用接口,强制降低偶合度。 3,Java通过接口和内部类两种机制来实现多继承。在类内部可以建立本类的实例,然后调用本类内的其他方法。
时间: 2024-10-17 05:18:31