构造函数
- 当在一个类中,没有提供构造函数时,系统会默认提供无参的构造函数。
- 如果类中包含了自己定义的有参构造函数,则系统不默认提供无参的构造函数,需要自己显性提供。
方法的重载
一个类中可以有多个名字,但是参数列表(参数的类型、个数、顺序)不同的多个方法,调用时,会根据不同的参数列表来选择对应的方法。构造方法也是可以重载的。
递归算法
在这里举一个典型的例子
下面代码求斐波那契数列第n项,斐波那契数列第一和第二项是1,后面每一项是前两项之和,即1、1、2、3、5、8、13 ...。
遇到算法问题,我们首先要考虑的就是能否转化为数学问题,由此得到F(n) = F(n-1)+F(n-2)。
下面是它的代码实现:
package com.example.test;
public class Test1 {
private static int a ;
public static void main(String[] args) {
int result = diGui(7);
System.out.println(result);
}
public static int diGui(int n) {
if(n>2) {
return diGui(n-1)+diGui(n-2);
}else {
return 1;
}
}
}
this关键字
是用来对当前的对象引用的,在调用本类的方法,会默认使用这个关键字,默认是可以不写的。this是在方法中使用的。
使用this关键字两种情况:
- 当类中某个非静态方法的参数名和类的某个成员变量名相同,为了避免作用范围覆盖了成员变量的作用范围,必须明确this。
private String name;
private String sex;
public Test1(String name,String sex) {
this.name = name;
this.sex = sex;
}
- 当某个构造函数中出现this,那么这个构造方法将调用本类的其他的方法。
public Test1(String name) {
this("liujin","sdasad");
name = "dasdad";
}
继承
在java中只支持单继承,还有就是子类只继承父类的属性和方法,不自动继承父类的构造函数。
super
super关键字是用来对父类的引用,在继承之后,可以通过super显式调用父类的方法。
还有一点最重要就是调用父类的构造方法,super必须是第一句,否则会报错的。
Object中重要的方法
- toString:返回代表该对象值的字符串,如果没有重写的话,返回的是包名.类名@内存地址的十六进制整数值。
- equals 测试某个对象是否相等,如果没有重写,是通过比较两个对象是否指向同一个内存地址。
- hashcode 返回对象的哈希码值 不同对象的哈希码值是不同,同一个对象执行多次哈希码值是不变的。
- getclass 返回当前运行的类名。
Test1 t = new Test1();
Test1 t1 = new Test1();
System.out.println(t.equals(t1));
System.out.println(t.hashCode());
System.out.println(t.toString());
System.out.println(t.getClass());
动态绑定
指的是在执行期间而不是编译时判断所引起的对象的实际类型
动态绑定发生条件
- 要有继承
- 要有重写
- 要有父类变量指向子类对象
- 要有父类变量调用重写方法
代码如下
public class ChaZuo {
public void tongDian() {
System.out.println("你可以使用你的电器");
}
}
public class Compter extends ChaZuo {
@Override
public void tongDian() {
// TODO Auto-generated method stub
super.tongDian();
System.out.println("现在可以看电脑了");
}
}
public class Tv extends ChaZuo {
@Override
public void tongDian() {
// TODO Auto-generated method stub
super.tongDian();
System.out.println("现在可以看电视");
}
}
public void shiYong(ChaZuo c) {
c.tongDian();
}
Judge j = new Judge();
j.shiYong(new Tv());
j.shiYong(new Compter());
java修饰符
静态变量
- 类中的静态变量属于类,而不是属于某个特定的对象。
- 类的静态成员可以与类的名称一起用,而无需创建类对象。
- 静态变量或方法可可以称作累的变量和方法
- 在整个类中静态变量的副本只有一个。
- 引用静态变量时建议使用类名来调用。
- static 变量实际上就是全局变量。
静态方法
- 类的静态方法只能访问其他的静态成员,不能访问非静态的成员。
- 静态方法中没有this。
- 静态方法不能被覆盖为非静态方法。
静态代码块
- 静态代码块在该类加载时执行一次
- 只能初始化类的静态成员。
单例模式
采取一定的方法保证在整个软件系统中,某个类只能存在一个对象实例。
单例模式两种形式
- 定义一个类,构造函数设置为private,定义一个静态实例对象,然后通过暴露一个方法,来获取类的对象。
public class Test4 {
private static final Test4 t = new Test4();//这个修饰确保只有一个对象
private Test4() {
}
public static Test4 getObject() {
return t;
}
}
- 不用每次生成对象,在第一次使用给的时候判断。
private static Test5 t = null;
public static synchronized Test5 getInstance() {
if(t==null) {
t = new Test5();
}
return t;
}
一般默认是第一种方法比较好。
final
- final修饰类是不可以继承
- final修饰方法,表示子类不能覆盖这个方法。
- 一个final方法,只能被实现一次。
- 如果一个类为final类,那么它的所有方法都为隐式final方法。
- final修饰变量,变量只能被初始化一次,然后就不能对其值进行修改。
- 一个final变量实质是一个常量。
abstract
- abstract修饰类为抽象类,不能被实例化。
- 构造函数和static方法不能抽象。
- 一个抽象类中方法可以有具体方法,也可以有抽象方法,但如果一个类中有抽象方法,那一定是抽象类。
接口
接口的定义:接口就是一套规范,在这些规范中只规定了必须实现哪些功能,但是没有规定如何进行实现。而实现的接口是由具体类来实现的。
接口总结
- 使用interface关键字来定义接口,在接口类中只需要申明方法,没有方法的主体,这些方法就是抽象方法。
- 接口中可以定义常量
public static final 修饰
- 在java中可以实现多个接口
注意带点补充
在java中,系统可以对成员变量进行默认的初始化,不会对局部变量进行默认初始化,局部变量不初始化会报错。
UML
面向对象设计思想,这种思想建立一般经过面向对象的分析(OOA),面向对象的设计后(OOD),才是面向对象的编(OOP)。 OOA主要是分析显示业务系统形成需求文档,OOD是用面向对象的思维将OOA形成的文档进行细化后转成计算机领域的对象模型,在这个转化过程中需要使用一种统一的符号来描述,UML(统一建模语言)
UML编制对象模型图分类
- 静态,静态图有助于设计包名、类名、属性。
- 动态,动态图有助于设计逻辑、代码或方法体。
类定义的特性划分
- 非静态成员内部类
- 局部内部类
- 静态成员内部类
- 匿名内部类
内部类都是一个独立的类,编译完的.class文件以外部类类名¥内部类类名.class。
由于内部类在一个类的内部作为外部类的一个成员出现,所以他们可以任意访问外部类的成员变量。
在内部类中,不能定义静态变量。
内部类作为外部类的成员出现的,外部类不可以访问内部类的成员,但是内部类可以访问外部类的成员,包括private,内部类相当与外部类的闺蜜,外部类与其他类之间就像普通朋友,米有可以知道外部类的一切,普通朋友只能知道外部类公布的东西,这样的好处的:高内聚,低耦合。
下面是几种内部类对外部类的引用
- 非静态成员内部类
public class Test5 {
//private int i =9;
class in{
int i= 10;
public void go() {
System.out.println(this.i);//i
}
}
}
在非静态成员内部类中,如果是访问自己定义的属性,可以直接访问,也可以通过this关键字访问。
public class Test5 {
private int i =9;
class in{
// int i= 10;
public void go() {
System.out.println(i);//Test5.this.i
}
}
}
在非静态成员内部类中,如果外部类和内部类的属性同名,可以通过外部类类名.this.外部类成员变量名
测试代码:
Test5 test = new Test5();
Test5.in t = test.new in();
t.go();
- 局部内部类
局部内部类也叫方法内部类。
public class Test5 {
int i = 8;
public void go() {
class Test9{
int i = 10;
public void share(int i) {
System.out.println(i);//获取形参
System.out.println(this.i);//获取内部类的变量
System.out.println(Test5.this.i);//获取同名的外部类的变量
}
}
Test9 t = new Test9();//构造内部类的对象
t.share(6);//调用内部类的方法
}
}
测试代码如下:
Test5 tes = new Test5();
tes.go();
上面这些获取参数的方法,和非静态内部类想类似,这里就不多讲。
局部内部类如果要访问外部类中方法的局部变量,必须给变量定义成final,因为方法的生命周期在调用时村内在,访问调用后就结束,内部类的实例并不会消失,所以要提高局部变量的生命周期。
-静态内部类
用static来修饰的内部类,这个类就相当与一个外部定义的类,在其中可以申明静态或非静态成员。
public class Test5 {
int d = 7;
static int i =9;
static class inner {
int p = 10;
static int y = 11;
public void go() {
System.out.println(i);//访问外部类的静态成员变量
System.out.println(p);//访问内部类的非静态成员变量
System.out.println(y);//访问内部类的静态成员变量
// System.out.println(d);//不可以访问外部类的非静态变量
}
}
}
inner in = new inner();
in.go();//这里无需创建外部类的对象,直接创建内部类的对象。
由于静态只能和静态交流,所以静态内部类只能访问外部类的静态变量和方法,非静态不能访问,但是可以访问自己静态内部类的非静态和静态变量,因为默认情况下静态内部类的内部都是静态的。
- 匿名内部类
匿名内部类就是没有名字的内部类,所以匿名内部类是没有构造函数的。如果匿名内部类继承了一个含有带参数构造器的父类,则创建它的时候就必须带上参数,并且在实现的过程中使用super关键字调用相应的内容。
普通的内部类
package com.example.test;
public class Test5 {
public static void main(String[] args) {
class B implements A{
@Override
public void fun() {
// TODO Auto-generated method stub
System.out.println("a 我在玩");
}
}
new Test5().panDuan(new B());
}
public void panDuan(A a) {
a.fun();
}
}
匿名内部类
package com.example.test;
public class Test4 {
public static void main(String[] args) {
new Test4().panDuan(new A() {//在这里你可能会觉得奇怪,
//接口不是不可以产生对象,这里其实是它的实现类产生对象只是没有去名字
@Override
public void fun() {
// TODO Auto-generated method stub
System.out.println("a 正在玩");
}
});
}
public void panDuan(A a) {
a.fun();
}
}
- 匿名内部类要访问方法内的局部变量,必须要定义成final。
匿名内部类不能定义任何静态成员、方法、和类。
内部类实例化方法(这个是针对非静态内部类的方法)
通过外部类的非静态方法,(就是普通方法)中,调用内部类的对象,来实例化。
- 通过外部类的静态main来实例化,上面测试就是。
- 在内部类中通过this来表示内部类的实例。