面向对象编程
面向对象的概念
OOP:Object Oriented Programming
class 和 instance 是“模板”和“实例”的关系 ==>
类:class,对象模板
实例:instance,具体对象
class用字段(field)封装了数据,不同的instance拥有各自独立的field
通过 **变量.字段名** 访问某个字段
指向 instance 的变量都是引用变量
数据封装
方法
方法封装了访问实例字段的逻辑
实例字段修饰符
public:外部代码可以访问该字段
private:外部代码无法访问该字段
方法修饰符
public:外部代码可以访问该方法
private:外部代码无法访问该方法
方法是一组执行语句,遇到return返回
void表示不返回任何值(注意区分null)
方法命名规范
方法内部的隐私变量this
构造方法Constructor
构造方法可以在new操作时初始化实例对象
构造方法名就是类名
构造方法没有返回值
编译器会为没有定义构造方法的类自动生成默认构造方法(无参数、无执行语句)
如果我们自定义了构造方法,编译器就不再自动创建默认构造方法
初始化顺序:
1)初始化字段(没有赋值的字段初始化为默认值,基本类型=0,引用类型=null)
2)执行构造方法代码
可以定义多个构造方法,编译器根据参数数量、位置和类型自动判断使用哪个
可以在一个构造方法中调用其他构造方法,便于代码的复用,调用方法是this(...)
方法重载 Overload
指方法名相同,单参数不同:
1)类型不同
2)数量不同
3)位置不同
方法重载的目的是方便调用
重载方法应该完成相同的功能,参考String的indexOf()
1)indexOf(String str)
2)indexOf(String str1, int FromIndex)
不要去交换参数顺序
1)indexOf(String str, int fromIndex)
2)indexOf(int fromIndex, String str)
重载方法返回值类型应该相同
继承和多态
继承
继承是面向对象编程的代码复用方式
Java使用extend继承
被继承类:超类,父类,基类 继承类:子类,派生类
Java只允许继承一个类
Object是所有类的根类
protected修饰的字段和方法可以被子类访问,protected把字段和方法的访问权限控制在了继承树内部
super表示父类
没有调用super()时编译器会自动生成super()语句,如果父类没有默认构造方法,子类就必须显示调用super()
向上转型和向下转型 Upcasting Downcasting
子类类型可以安全地向上转型为父类类型
父类类型可以强制向下转型为子类类型(可能报错ClassCastException)
我们在做向下转型的时候,可以先用instanceof判断类型
继承和组合
继承是is关系
组合是has关系
多态Polymorphic
方法覆盖:
子类覆写父类的方法,Override
方法签名如果不同就不是Override,而是创建了一个新方法
加上@Override可以让编译器帮助检查是否进行正确的覆写
@Override不是必需的
多态:
针对某个类型的方法调用,其真正执行的方法取决于运行时实际类型的方法
Java的实例方法调用是基于运行时实际类型的动态调用 ===> 多态
对某个类型调用方法,执行的方法可能是某个子类的覆写方法
允许添加更多类型的子类来扩展功能
Object定义的几个重要的方法:
1)toString:把instance输出为String
2)equals:判断两个instance是否逻辑相等
3)hashCode:计算一个instance的哈希值
final
用final修饰的方法不能被Override
用final修饰的类不能被继承
用final修饰的字段初始化后不能重新赋值
抽象类和接口
抽象类 Abstract Class
抽象方法用abstract修饰,抽象方法没有任何执行语句;因为无法执行抽象方法,所以这个类也必须申明为抽象类(abstract class)
无法实例化一个抽象类
含有抽象方法的类称为抽象类
抽象类的作用:
1)被继承
2)强迫子类实现抽象方法
3)抽象方法相当于定义“规范”
面向抽象编程的本质:
1)上层代码只定义规范
2)不需要子类即可编译
3)具体逻辑由不同子类实现,调用者并不关心
接口 Interface
接口定义了纯抽象规范,使用interface声明一个接口,接口只有抽象方法
实现interface使用implements
一个class可以实现多个interface
接口:
1)不能定义实例字段
2)不能定义普通方法
3)可以定义default方法(JDK>=1.8)
一个接口可以extends另一个接口,相当于扩展接口方法
接口层次代表抽象程度
接口也是数据类型,适用于向上转型和向下转型
abstract class | interface | |
---|---|---|
继承 | 只能extends一个class | 可以implements对个interface |
字段 | 可以定义实例字段 | 不能定义实例字段 |
抽象方法 | 可以定义抽象方法 | 可以定义抽象方法 |
非抽象方法 | 可以定义非抽象方法 | 可以定义default方法 |
包和classpath
静态字段和方法
用static修饰的字段:静态字段,属于class,不属于实例
普通字段在每个实例中都有自己的一个独立“空间”
静态字段只有一个共享“空间”,所有实例都共享该字段
访问静态字段:类名.静态字段 不推荐使用 实例变量.静态字段
用static修饰的方法:静态方法,属于class,不属于实例
调用实例方法必须通过实例变量
调用静态方法不需要实例变量
静态方法类似其他编程语言的函数
访问静态方法:类名.静态方法 不推荐使用 实例变量.静态方法
静态方法不能访问this变量,但可以访问静态字段
静态方法不能访问实例字段
静态方法常用用于工具类(Arrays.sort()、Math.random())和辅助方法
Java程序的入口main()也是静态方法
包 Packages
package用于解决类名冲突:
Java完整类名=包名+类名;JVM只看完整类名,编译器编译后的class只含完整类名
包可以有多层结构,包没有父子关系(例如:java.util和java.util.zip是不同的包,两者没有任何关系)
包作用域
位于同一个包的类,可以访问包作用域的字段和方法
不用public、protected、private修饰的字段和方法就是包的作用域
引用其他类的方法
使用完整类名;先import,再使用类名;可以使用*(不推荐)
static import可以导入一个类的静态字段和静态方法,很少使用
查找class
编译器查找class完整类名的步骤:
1)根据完整类名查找
2)查找当前package
3)查找import的class
4)查找java.lang的class
5)编译错误
默认自动import当前package,默认自动import java.lang.*
最佳实践
包名使用倒置域名确保唯一,不要和java.lang的类重名,不用和JDK常用类重名
作用域
访问权限
访问权限指一个类内部,能否引用另一个类以及它的字段和方法
方法权限有public、protected、private和package四种
final不是访问权限
最佳实践:最小化暴露对外方法
局部变量
方法内部定义的变量时局部变量(包括方法参数名)
局部变量作用域由所在语句块{...}决定
classpath和jar
classpath
classpath是环境变量,指示JVM如何搜索class,路径和操作系统相关
假设classpath是 .;C:\work\project1\bin;C:\shared
JVM在加载com.feiyangedu.Hello这个类时,依次查找:
<当前目录>\com\feiyangedu\Hello.class
C:\work\project1\bin\com\feiyangedu\Hello.class
C:\shared\com\feiyangedu\Hello.class
在某个路径下找到了,就不再继续搜索;如果都没有找到,就报错
classpath设置方法:
1)在系统环境变量设置(不推荐)
2)启动JVM时用-classpath或-cp设置(推荐)
java -classpath C:\work\bin;C\shared com.feiyangedu.Hello
java -cp C:\work\bin;C\shared com.feiyangedu.Hello
Eclipse自动传入当前工程bin目录作为classpath
jar
jar包是zip格式的压缩文件,包含若干class文件
jar包相当于目录
使用jar包来避免大量目录和class文件
创建jar包:
1)JDK的jar命令
2)Maven等工具
3)压缩为zip然后改名为jar
jar包可以有一个特殊的/META-INF/MANIFEST.MF文件来指定Main-Class
例如
Mainfest-Version: 1.0
Main-Class: com.feiyangedu.sample.Main
X-Copyright: dafjlaf...
X-Build-Version: 1.0
Java核心类
字符串和编码
字符串
Java字符串的特点:
1)字符串对象可以直接使用 双引号 “...” 表示
2)内容不可变
3)使用equals(Object)判断是否相等,equalsIgnoreCase(String)忽略大小写比较
字符串常用操作:
1)是否包含子字符串:contains、indexOf、lastIndex、startsWith、endsWith
boolean contains(CharSequence)
int indexOf(String)
int lastIndex(String)
boolean startsWith(String)
boolean endsWith(String)
2)去除首尾空白字符:trim
空白字符包括:空格,\t,\r,\n
trim()不改变字符串内容,而是返回新字符串
3)提取子串:substring
4)大小写转换:toUpperCase、toLowerCase
5)替换子串:replace、replaceAll(正则表达式替换)
6)分割:split
String[] split(String)
7)拼接:join
static String join()
String和其他数据类型互相转换
// 把任意数据转换为String
static String valueOf(int)
static String valueOf(boolean)
static String valueOf(Object)
// 把String转换为其他类型
static int Integer.parseInt(String)
static Integer Integer.valueOf(String)
String和char[]互相转换
// String转换为char[]
char