匿名对象
- 我们也可以不定义对象的句柄,而直接调用这个对象的方法。这
样的对象叫做匿名对象。
:new Person().shout();
- 使用情况
如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
我们经常将匿名对象作为实参传递给一个方法调用。
类的成员
属性
语法格式:
修饰符 数据类型 属性名 = 初始化值 ;
说明1: 修饰符
常用的权限修饰符有:private、缺省、protected、public
其他修饰符:static、final (暂不考虑)
举例:
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}
成员变量与局部变量
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
成员变量(属性)和局部变量的区别?
内存位置
对象属性的默认初始化赋值
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型,如上面的Person及前面讲过的数组。
类的成员之二:方 法
方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中
也称为函数或过程。
将功能封装为方法的目的是,可以实现代码重用,简化代码
Java里的方法不能独立存在,所有的方法必须定义在类里。
方法的调用
方法通过方法名被调用,且只有被调用才会执行。
方法被调用一次,就会执行一次
没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可
以不必使用return语句。如果使用,仅用来结束方法。
定义方法时,方法的结果应该返回给调用者,交由调用者处理。
方法中只能调用方法或属性,不可以在方法内部定义方法。
方法的重载
重载的概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
**重载的特点:**与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
方法参数的值传递机制
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
形参:方法声明时的参数
实参:方法调用时实际传给形参的参数值
Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
面向对象特征之一:封装和隐藏
我们程序设计追求“高内聚,低耦合”。
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
低耦合 :仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提
高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露
的暴露出来。这就是封装性的设计思想。
Java中通过将数据声明为私有的(private),再提供公共的(public)
方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的:
隐藏一个类中不需要对外提供的实现细节;
使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
便于修改,增强代码的可维护性;
类的成员之三:构造器(构造方法)
构造器的特征
它具有与类相同的名称
它不声明返回值类型。(与声明为void不同)
不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值
构造器的作用:创建对象;给对象进行初始化
根据参数不同,构造器可以分为如下两类:
隐式无参构造器(系统默认提供)
显式定义一个或多个构造器(无参、有参)
注 意:
Java语言中,每个类都至少有一个构造器
默认构造器的修饰符与所属类的修饰符一致
一旦显式定义了构造器,则系统不再提供默认构造器 一个类可以创建多个重载的构造器
父类的构造器不可被子类继承
构造器重载
属性赋值过程
赋值的位置:
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过“对象.属性“或“对象.方法”的方式赋值
赋值的先后顺序:
① - ② - ③ - ④
JavaBean
类是公共的
有一个无参的公共的构造器
有属性,且有对应的get、set方法
关键字—this
在Java中,this关键字比较难理解,它的作用和其词义很接近。
它在方法内部使用,即这个方法所属对象的引用;
它在构造器内部使用,表示该构造器正在初始化的对象。
this 可以调用类的属性、方法和构造器 什么时候使用this关键字呢?
当在方法内需要用到调用该方法的对象时,就用this。
具体的:我们可以用this来区分属性和局部变量。
比如:this.name = name;
使用this调用本类的构造器
注意
可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其
他的构造器!
明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了
“this(形参列表)”
"this(形参列表)“必须声明在类的构造器的首行!
在类的一个构造器中,最多只能声明一个"this(形参列表)”
关键字—package
package语句作为Java源文件的第一条语句,指明该文件中定义的类所在
的包。(若缺省该语句,则指定为无名包)。
MVC设计模式
JDK中主要的包介绍
面向对象特征之二:继承性(inheritance)
为什么要有继承?:多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
此处的多个类称为子类(派生类),单独的这个类称为父类(基类 或超类)。可以理解为:“子类 is a 父类”
类继承语法规则:
class Subclass extends SuperClass{ }
作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提。
子类继承了父类,就继承了父类的方法和属性。
在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和
方法。
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,
而是对父类的“扩展”。
关于继承的规则:
子类不能直接访问父类中私有的(private)的成员变量和方法。
Java只支持单继承和多层继承,不允许多重继承
一个子类只能有一个父类
一个父类可以派生出多个子类
class SubDemo extends Demo{ } //ok
class SubDemo extends Demo1,Demo2…//error
方法的重写(override/overwrite)
在子类中可以根据需要对从父类中继承来的方法进行改造,也称
为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
要求:
- 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
- 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
- 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
子类不能重写父类中声明为private权限的方法 - 子类方法抛出的异常不能大于父类被重写方法的异常
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为
static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
关键字—super
在Java类中使用super来调用父类中的指定操作:
super可用于访问父类中定义的属性
super可用于调用父类中定义的成员方法
super可用于在子类构造器中调用父类的构造器
注意:
尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super的追溯不仅限于直接父类 super和this的用法相像,this代表本类对象的引用,super代表父类的内存
空间的标识
调用父类的构造器
子类中所有的构造器默认都会访问父类中空参数的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参
数列表)或者super(参数列表)语句指定调用本类或者父类中相应的
构造器。同时,只能”二选一”,且必须放在构造器的首行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又
没有无参的构造器,则编译出错
public class Person {
private String name;
private int age;
private Date birthDate;
public Person(String name, int age, Date d) {
this.name = name;
this.age = age;
this.birthDate = d; }
public Person(String name, int age) {
this(name, age, null);
}
public Person(String name, Date d) {
this(name, 30, d);
}
public Person(String name) {
this(name, 30);
} }
public class Student extends Person {
private String school;
public Student(String name, int age, String s) {
super(name, age);
school = s; }
public Student(String name, String s) {
super(name);
school = s; }
// 编译出错: no super(),系统将调用父类无参数的构造器。
public Student(String s) {
school = s; } }
this和super的区别
面向对象特征之三:多态性
多态性,是面向对象中最重要的概念,在Java中的体现:
对象的多态性:父类的引用指向子类的对象
可以直接应用在抽象类和接口上
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法) “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
对象的多态 —在Java中,子类的对象可以替代父类的对象使用
父类的引用指向子类的对象
一个引用类型变量如果声明为父类的类型,但实际引用的是子类
对象,那么该变量就不能再访问子类中添加的属性和方法
多态作用:
提高了代码的通用性,常称作接口重用
前提: 需要存在继承或者实现关系
有方法的重写
成员方法:
编译时:要查看引用变量所声明的类中是否有所调用的方法。
运行时:调用实际new的对象所属的类中的重写方法。 成员变量:
不具备多态性,只看引用变量所声明的类。
Object 类的使用
Object类是所有Java类的根父类
如果在类的声明中未使用extends关键字指明其父类,则默认父类 为java.lang.Object类
public class Person {
…
}
等价于:
public class Person extends Object {
…
}
Object类中的主要结构
==操作符与equals方法
= =:
基本类型比较值:只要两个变量的值相等,即为true。
int a=5; if(a6){…}
引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,才
返回true。
Person p1=new Person();
Person p2=new Person();
if (p1p2){…} 用“”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本
数据类型除外),否则编译出错
equals():所有类都继承了Object,也就获得了equals()方法。还可以重写。 只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象。
格式:obj1.equals(obj2)
特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;
原因:在这些类中重写了Object类的equals()方法。
当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都
相等
重写equals()方法的原则
面试题:==和equals的区别
toString() 方法
包装类(Wrapper)的使用
包装类(Wrapper)的使用
基本数据类型包装成包装类的实例 ---装箱
通过包装类的构造器实现:
int i = 500; Integer t = new Integer(i);
还可以通过字符串参数构造包装类对象:
Float f = new Float(“4.56”);
Long l = new Long(“asdf”); //NumberFormatException
获得包装类对象中包装的基本类型变量 ---拆箱
调用包装类的.xxxValue()方法:
boolean b = bObj.booleanValue();
拆箱:将数字包装类中内容变为基本数据类型。
int j = t.intValue(); // j = 500,intValue取出包装类中的数据
关键字:static
使用范围:
在Java类中,可用static修饰属性、方法、代码块、内部类
被修饰后的成员具备以下特点:
随着类的加载而加载
优先于对象存在
修饰的成员,被所有对象所共享
访问权限允许时,可不创建对象,直接被类调用
类方法(class method)
没有对象的实例时,可以用类名.方法名()的形式访问由static修饰的类方法。
在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
因为不需要实例就可以访问static方法,因此static方法内部不能有this。(也
不能有super ? YES!)
static修饰的方法不能被重写
class Person {
private int id;
private static int total = 0;
public static void setTotalPerson(int total){
this.total=total; //非法,在static方法中不能有this,也不能有super
}
public Person() {
total++;
id = total;
}}
public class PersonTest {
public static void main(String[] args) {
Person.setTotalPerson(3);
} }
单例 (Singleton)设计模式
单例(Singleton)设计模式-饿汉式
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single = new Singleton();
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
return single; } }
单例(Singleton)设计模式-懒汉式
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single;
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
if(single == null) {
single = new Singleton();
}
return single; } }
单例模式的优点:
由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的
产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可
以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方
式来解决。
设计模式-应用场景
网站的计数器,一般也是单例模式实现,否则难以同步。
应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志
文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库
资源。 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置
文件数据,都生成一个对象去读取。 Application 也是单例的典型应用
Windows的Task Manager (任务管理器)就是很典型的单例模式
Windows的Recycle Bin (回收站)也是典型的单例应用。在整个系统运行过程
中,回收站一直维护着仅有的一个实例。
类的成员之四:代码块
代码块(或初始化块)的作用:
对Java类或对象进行初始化
代码块(或初始化块)的分类:
一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块(static block),没有使用static修饰的,为非静态代码块。
static代码块通常用于初始化static的属性
class Person {
public static int total;
static {
total = 100;//为total赋初值
}
…… //其它属性或方法声明
}
静态代码块:用static 修饰的代码块
- 可以有输出语句。
- 可以对类的属性、类的声明进行初始化操作。
- 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
- 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
- 静态代码块的执行要先于非静态代码块。
6. 静态代码块随着类的加载而加载,且只执行一次
非静态代码块:没有static修饰的代码块
- 可以有输出语句。
-
- 可以对类的属性、类的声明进行初始化操作。
-
- 除了调用非静态的结构外,还可以调用静态的变量或方法。
-
- 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
-
- 每次创建对象的时候,都会执行一次。且先于构造器执行。
关键字:final
在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。
final标记的类不能被继承。提高安全性,提高程序的可读性。
String类、System类、StringBuffer类 final标记的方法不能被子类重写。
比如:Object类中的getClass()。
final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只
能被赋值一次。
final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋
值,然后才能使用。
final double MY_PI = 3.14;
抽象类与抽象方法
用abstract关键字来修饰一个类,这个类叫做抽象类。
用abstract来修饰一个方法,该方法叫做抽象方法。
抽象方法:只有方法的声明,没有方法的实现。以分号结束:
比如:public abstract void talk();
含有抽象方法的类必须被声明为抽象类。
抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类
不能用abstract修饰变量、代码块、构造器;
不能用abstract修饰私有方法、静态方法、final的方法、final的类
多态的应用:模板方法设计模式(TemplateMethod)
接口(interface)
一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方
法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
接口的特点:
用interface来定义。 接口中的所有成员变量都默认是由public static final修饰的。 接口中的所有抽象方法都默认是由public abstract修饰的。
定义Java类的语法格式:先写extends,后写implements
class SubClass extends SuperClass implements InterfaceA{ }
一个类可以实现多个接口,接口也可以继承其它接口。
实现接口的类中必须提供接口中所有方法的具体实现内容,方可实
例化。否则,仍为抽象类。
接口的主要用途就是被实现类实现。(面向接口编程)
与继承关系类似,接口与实现类之间存在多态性
接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲,
接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义
(JDK7.0及之前),而没有变量和方法的实现
一个类可以实现多个无关的接口
interface Runner { public void run();}
interface Swimmer {public double swim();}
class Creator{public int eat(){…}}
class Man extends Creator implements Runner ,Swimmer{
public void run() {……}
public double swim() {……}
public int eat() {……}
}