Java基础总结
title: java面向对象
date: 2017-08-31 09:33:48
tags: java
categories: Java
方法的定义、方法的重载、方法的递归调用。
类的定义、 类的声明、类的使用
方法
方法的定义
方法就是一段可以重复的代码段。
访问修饰符 返回值类型 方法名(){
方法主体
}
方法的重载
方法名称相同。但是参数的类型和个数不同,通过传递参数的个数和类型不同来完成不同的功能。
public void tell(int i){
}
public void tell (int i,int y){
}
方法的返回值类型,void类型不需要返回值,其他的类型都需要返回值。
方法的递归调用
一种特殊逇调用方式,就是方法自己调自己。
类
类的定义
类是对某一事物的描述,是抽象的。概念上的意义,对象是实际存在的该类事物的每一个个体,也被称为对象或实例。
类的声明
class Person{
public String name;
public int age;
public void tell() {
System.out.println("姓名:"+name+",年齡:"+age);
}
}
类的使用
public static void main(String[] args) {
Person person;//声明对象,开辟栈内存空间
person=new Person();//开辟堆内存空间
person.name="张三";
person.age=10;
person.tell();
}
通过关键字 new
开辟空间,实例化操作。
面向对象的三大特征
封装性
对外不可见。保护某些属性和方法不被外部所看见。
封装的实现:为属性和方法进行封装是通过关键字private声明的,实现该属性的set和get方法,为外部所访问。
class Person{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void tell() {
System.out.println("年龄:"+getAge());
}
}
public class PrivateDemo01 {
public static void main(String[] args) {
Person person=new Person();
person.setAge(160);
person.tell();
}
}
继承
扩展类的功能。可以说为:扩展父类的功能。
继承的实现
java中使用 extends
关键字完成继承
class 子类 extends 父类 {
}
继承的限制
在java 中只允许单继承 (一个儿子只能有一个亲生父亲)
子类不能直接访问父类的私有成员,那么如何进行访问父类的私有成员呢?需要子类实现get(),set()方法去进行访问。
class People { //新建一个People类
private int age; //封装属性
public int getAge() { //实现age属性的getAge(),setAge()方法。
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ExtendsDemo01 {
public static void main(String[] args) {
Worker worker=new Worker(); //实例化worker对象。
worker.setAge(100); //用setAge()方法设置worker的age属性。
System.out.println(worker.getAge());//用getAge()方法进行获取worker的age值。
}
}
子类对象的实例化过程
在子类对象实例化之前,必须先调用父类中的构造方法,之后调用子类构造方法。
class Father{ //新建一个People类
private int age; //私有age属性
private String name; //私有name属性
public Father(){ //构造方法
System.out.println("父类的构造方法");
}
}
class Son extends Father{ //新建Son类继承与Father
public Son() {
System.out.println("子类的构造方法");
}
}
public class ExtendsDemo02 {
public static void main(String[] args) {
Son son=new Son(); //实例化Son子类。构造方法不需要进行调用,直接实例化.
}
}
方法的重写
在继承中,也存在着重写的概念。其实就是子类定义了父类同名的方法。
定义:方法名称相同,返回值类型相同,参数也同。
重写限制:被子类重写的方法不能拥有比父类更加严格的访问权限 (private<default<public)
。
class A {
public void tell(int a) { //创建tell方法
System.out.println("我tell方法");
}
void say(){
System.out.println("我创造default的say方法");
}
}
class B extends A {
public void tell(int a) { //子类也创建tell方法(即为重写)
super.tell(10); //若要调用父类的方法,可以用super关键字来调用
System.out.println("我重写tell方法");
}
}
public class ExtendsDemo03 {
public static void main(String[] args) {
B b = new B();
b.tell(10);
}
}
void say(){
System.out.println("我的权限只能是default"); //不能修改为比父类更低的访问权限,例如修改为 private void say(){}
}
super关键字
强行调用父类的方法的执行
super不一定在重写中使用,也可以表示那些方法时从父类中继承而来的。
重写与重载的区别
No | 区别点 | 重载 | 重写 |
---|---|---|---|
1 | 单词 | Overloading | Overriding |
2 | 定义 | 方法名称相同,参数类型或个数不同 | 方法名称、参数的类型、返回值类型全部相同 |
3 | 权限 | 对权限没有要求 | 被重写 |
4 | 范围 | 发生在一个类中 | 发生在继承中 |
多态性
方法的重载,对象的多样性。
常见异常
数组越界异常
ArrayIndexOutOfBoundsException
数组格式化异常
NumberFormatException
算数异常
ArithmeticException
public class Exception {
public static void main(String[] args) {
int a=10;
int b=0;
int temp=0;
try {
temp=a/b;
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
}
}
}
空指针异常
NullPointerException
构造方法
访问修饰符 类名称(){
程序语句
}
注意点:
1.构造方法名称必须与类名一致。2.构造方法没有返回值。
构造方法主要是为类中的属性初始化
每个类在实例化之后都会调用构造方法,如果没有构造方法,程序在编译的时候回创建一个无参的什么都不做的构造方法
构造方法可以重载
class People{
int age;
String name;
public People(int a,String n) {
age=a;
name=n;
System.out.println("姓名:"+name+",年龄:"+age);
}
public People(int a) {
age=a;
System.out.println("年龄:"+a);
}
}
public class ClassDemo02 {
public static void main(String[] args) {
People people=new People(30,"小米");//构造方法
new People(23);
}
}
引用传递
class Ref1 {
int temp = 10;
}
public class RefDemo01 {
public static void main(String[] args) {
Ref1 ref1 = new Ref1();
ref1.temp = 20;
System.out.println(ref1.temp);
tell(ref1);
System.out.println(ref1.temp);
}
public static void tell(Ref1 ref2) {
ref2.temp = 30;
}
}
this
关键字
表示类中属性和调用方法
调用本类中的构造方法
表示当前对象
class People {
private String name;
private int age;
public People(String name, int age) {
this();
this.name = name;
this.age = age;
}
public People() {
System.out.println("无参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void tell() {
System.out.println("姓名:" + this.getName() + "年龄:" + this.getAge());
}
}
public class ThisDemo {
public static void main(String[] args) {
People people = new People("张三", 30);
people.tell();
}
}
static
关键字
使用 static 声明属性
static声明全局属性
使用static声明方法
直接通过类名调用
注意点:使用 static 方法的时候,只能访问 static 声明的属性和方法,而非 static 声明的属性和方法是不能访问的。
final关键字
- final关键字在java中称为完结器,表示最终的意思
- final能声明类、方法、属性.
使用final声明的类不能被继承
使用final声明的方法不能被重写
使用final声明的变量变成常量,常亮是不可以被修改的。
抽象类
- 概念:包含一个抽象方法的类。
- 定义格式:
abstract class ClassNmae{ 属性 方法 抽象方法 }
- 抽象方法:声明而未被实现的方法,抽象方法必须使用abstract关键字方法。
- 抽象类不能直接实例化
抽象类被子类继承,子类(如果不是抽象类)必须重写抽象类中的所有的抽象方法。
```
abstract class Abs { // 抽象类
private int age; // 私有成员变量public void tell() {
}
public abstract void say(); // 抽象方法
public abstract void print();
public void setAge(int age) { // 访问父类私有成员变量,只能通过实现set()和get()方法
this.age = age;
}public int getAge() {
return age;
}
}
class AbsDemo extends Abs { // 子类AbsDemo继承Abs,
public void say() {
System.out.println(getAge());
}
public void print() {
}
}
public class AbstractDemo01 {
public static void main(String[] args) {
AbsDemo absDemo = new AbsDemo(); // 实例化子类
absDemo.setAge(30);
absDemo.say(); // 子类AbsDemo必须重写抽象类中所有的抽象方法
absDemo.print();
}
}
```
接口
接口可以理解为一种特殊的类,里面全部是由全局变量和公共的抽象方法所组成。是Java中最重要的概念。
接口的格式:
interface interfaceName{
全部变量
抽象方法
}
接口的实现也必须通过子类,使用关键字implements,而且接口可以多实现的。
一个子类也可以同时继承抽象类和实现接口。
一个接口不能继承一个抽象类,但是却可以通过extends关键字同时继承多个接口。实现接口的多继承。
interface Inter1 { public static final int AGE = 100; public abstract void tell(); }
interface Inter2 {
public abstract void say();
}
interface Inter3 extends Inter1, Inter2 { // 接口多实现
}
abstract class Abs1 {
public abstract void print();
}
class A extends Abs1 implements Inter1, Inter2 { // 一个子类可以同时继承抽象类,以及多个接口。
public void tell() {
}
public void say() {
System.out.println("我吃");
}
public void print() {
}
}
public class InterDemo01 {
public static void main(String[] args) {
A a = new A();
a.tell();
System.out.println(Inter1.AGE);
a.say();
a.print();
}
}
```
对象接口的使用
interface USB { //创建一个USB接口
void start();
void stop();
}
class C { //创建一个类
public static void wrok(USB usb) { //静态方法,传递USB参数
usb.start();
System.out.println("工作中");
usb.stop();
System.out.println("");
}
}
class USBisk implements USB { //创建U盘的类,实现USB接口
public void start() {
System.out.println("U盘开始工作");
}
public void stop() {
System.out.println("U盘停止工作");
}
}
class Printer implements USB { //创建打印机的类,实现USB接口
public void start() {
System.out.println("打印机开始工作");
}
public void stop() {
System.out.println("打印机开始工作");
}
}
public class InterDemo02 {
public static void main(String[] args) {
C.wrok(new USBisk()); //每个类只是用一次,匿名对象方法调用
C.wrok(new Printer());
}
}
# 多态性
- 多态性的体现
方法的重载和重写
对象的多态性
- 对象的多态性
向上转型:程序会自动完成
父类 父类对象=子类实例
向下转型:强制类型转化
子类 子类对象=(子类)父类实例
先发生向上转型,在发生向下转型
instanceof 关键字
在java中可以使用
instanceof
关键字判断一个对象到底是不是一个类的实例
泛型
泛型是在jdk1.5之后新增的功能,泛型(Generic)
泛型可以解决数据类型的安全性问题,他主要的原理,是在类声明的时候通过一个标识表示类中某个属性 的类型或者是某个方法的返回值及参数类型。
格式:
访问权限 class 类名称<泛型,泛型。。。>{
属性
方法
}
对象的创建
> 类名称<具体类型> 对象名称=new 类名称 <具体类型>();
class Point<T>{
private T x;
private T y;
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
public class GenericDemo {
public static void main(String[] args) {
Point<String>point=new Point<String>();
point.setY("精度为:100");
point.setX("精度为:200");
System.out.println(point.getX()+point.getY());
}
}
构造方法使用泛型
构造方法中使用泛型:
构造方法可以为类中的属性初始化,那么如果类中的属性通过泛型指定,而又需要通过构造方法设置属性内容的时候,那么构造方法的定义与之前并无不同,不需要像声明类那么指定泛型
设置多个泛型
设置多个泛型直接在<>中添加多个泛型就可以了
class Gen<K,T>{
private T take;
private K key;
public T getTake() {
return take;
}
public void setTake(T take) {
this.take = take;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
}
public class GenericDemo02 {
public static void main(String[] args) {
Gen<String,Integer>gen=new Gen<String,Integer>();
gen.setTake(10);
gen.setKey("我是key");
System.out.println(gen.getKey()+gen.getTake());
}
}
在使用泛型方法的时候,也可以传递或返回一个泛型数组
public class CenericDemo07 {
public static void main(String[] args) {
String arr[]= {"nihao","nihaoya","nizhidao"};
tell(arr);
}
public static <T>void tell(T arr[]){
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
Java 集合
集合可以理解为一个动态的对象数组,不同的是集合中的对象内容可以任意扩充
集合的特点
性能高
容易扩展和修改
Collection接口
常用子类:List、Set、Queue
List接口
List接口可以存放任意的数据,而且在List接口中内容是可以重复的
List接口常用子类:ArrayList、Vector
public class ListDemo01 { //ArrayList的使用
public static void main(String[] args) {
List<String> lists = null;
lists = new ArrayList<String>();
lists.add("A"); //添加元素
lists.add("B");
for (int i = 0; i < lists.size(); i++) { //通过for循环打印集合所有数据
System.out.println(lists.get(i));
}
}
}
List 常用操作:
- 判断集合是否为空:blooean isEmpty()
- 查找指定的对象是否存在:int indexOf(Object o)
lists.remove(0); //移除索引为0的元素
System.out.println("删除之后------");
for (int i = 0; i < lists.size(); i++) {
System.out.println(lists.get(i)); //打印集合中所有元素
} System.out.println("集合是否为空?"+lists.isEmpty());
System.out.println("查找对象是否存在:"+lists.indexOf("B")); //显示当前元素的索引位置
ArrayList与Vector比较
比较 | ArrayList | Vector |
---|---|---|
推出时间 | JDK1.2之后推出 | JDK1.0推出 |
性能 | 采用异步方式,性能高 | 采用同步处理方式,性能低 |
线程安全 | 属于非线程安全 | 属于线程安全 |
Set接口
Set接口不能加入重复元素,但是可以排序
Set接口常用子类
- 散列存放:HashSet
- 有序存放:TreeSet
public class SetDemo01 {
public static void main(String[] args) {
Set<String>set=null;
// HashSet实现,散列存放
/*
set=new HashSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
set.add("F");
System.out.println(set);
*/
// TreeSet实现,有序存放
set=new TreeSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
set.add("F");
System.out.println(set);
}
}
Iterator接口
- 集合输出的标准操作: 标准做法,使用Interator接口
- 操作原理: Iterator是专门的迭代输出接口,迭代输出就是将一个个进行判断,判断其是否有内容,如果有内容则把内容取出。
public class IteratorDemo01 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
list.add("F");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String string = iterator.next();
if ("A".equals(string)) { //移除A元素
iterator.remove();
} else {
System.out.println(string);
}
}
}
}
Map接口
file类
文件的创建,删除,重命名。
在eclipse中,敲入下方源码,alt+鼠标左键,可以查看file类源代码,方法名称等。
../
代表上级目录,../../
代表上级上级目录
当前文件是否为文件:file.isFile()
当前文件的路径:file.isDirectory()
删除文件:file.delete();
创建文件:file.createNewFile();
文件是否存在:file.exists()
重命名方法:file.renameTo();
创建文件夹:folder.mkdir(); 只能创建一级文件夹
创建多级文件夹:folder.mkdirs();
public class FileDemo01 {
public static void main(String[] args) {
File file = new File("../hello.txt");
// 是否存在
if (file.exists()) {
// 文件
System.out.println("当前文件是否为文件" + file.isFile());
// 路径(文件夹)
System.out.println("当前文件的路径" + file.isDirectory());
} else {
System.out.println("文件不存在");
try {
file.createNewFile();
System.out.println("文件已经被成功创建");
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件无法被创建");
}
}
}
}
public class FolderDemo01 {
public static void main(String[] args) {
// File folder = new File("my new folder/one/two/three/main");
// if (folder.mkdirs()) {
// System.out.println("文件夹创建成功");
// } else {
// if (folder.exists()) {
// System.out.println("文件已经存在不能再创建");
// } else {
// System.out.println("文件夹创建失败");
// }
// }
//
// 修改文件夹的名称,移动文件夹
File folder = new File("my new folder-new/one/2");
File newfolder = new File("my new folder-new/2");
if (folder.renameTo(newfolder)) {
System.out.println("done");
} else {
System.out.println("file");
}
}
}
文件属性的读取
public class ReadFileDemo01 {
public static void main(String[] args) {
File file = new File("test.txt");
// 判断文件是否存在
System.out.println("判断文件是否存在:" + file.exists());
// 读取文件名称
System.out.println("读取文件名称:" + file.getName());
// 读取文件路径
System.out.println("读取文件路径:" + file.getPath());
// 读取文件绝对路径
System.out.println("读取文件绝对路径:" + file.getAbsolutePath());
// 获取文件的父级路径
System.out.println("获取文件的父级路径:" + new File(file.getAbsolutePath()).getParent());
// 读取文件大小
System.out.println("读取文件大小:" + (float) file.length() / 1000 + "kb");
// 判断文件是否被隐藏
System.out.println("判断文件是否被隐藏:" + file.isHidden());
// 判断文件是否可读
System.out.println("判断文件是否可读:" + file.canRead());
// 判断文件是否可写
System.out.println("判断文件是否可写:" + file.canWrite());
// 判断文件是否为文件夹
System.out.println("判断文件是否为文件夹:" + file.isDirectory());
}
}
文件属性的设置
file.setReadable(false);
// 将文件设定为可读
file.setWritable(true);
// 将文件设定为只读
file.setReadOnly();
遍历文件夹
public class FileDemo03 {
public static void main(String[] args) {
// printFiles(new File("/Users/macinosh/eclipse-workspace"));
printFiles(new File("../test"), 1);
}
private static void printFiles(File dir, int tab) {
// 如果是一个文件夹的前提,把文件遍历出来
if (dir.isDirectory()) {
File next[] = dir.listFiles();
for (int i = 0; i < next.length; i++) {
for (int j = 0; j < tab; j++) {
System.out.print("|--");
}
System.out.println(next[i].getName());
if (next[i].isDirectory()) {
printFiles(next[i], tab + 1);
}
}
}
}
}
文件的简单读写
public class FileDemo04 {
public static void main(String[] args) {
File file = new File("text.txt");
if (file.exists()) {
System.err.println("exist");
try {
// 用于文件输入3个流
FileInputStream fis = new FileInputStream(file); // 创建文件输入流,字节流
InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); // 创建文件输入流的reader,
//字符流,当字节流转换为字符流的时候,就需要指定文本的编码
BufferedReader br = new BufferedReader(isr); // 创建带有缓冲区的输入流reader
String Line;
while ((Line = br.readLine()) != null) { // 读取内容
System.out.println(Line);
}
// 关闭文件的输入流,先打开的后关闭,后打开的先关闭
br.close();
isr.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 文件的输出流
try {
File newfile = new File("newtext.txt");
FileOutputStream fos = new FileOutputStream(newfile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("作者:汉乐府\n");
bw.write("青青园中葵,朝露待日晞。\n");
bw.write("阳春布德泽,万物生光辉。\n");
bw.write("常恐秋节至,焜黄华叶衰。\n");
bw.write("百川东到海,何时复西归?\n");
bw.write("少壮不努力,老大徒伤悲。\n");
bw.close();
osw.close();
fos.close();
System.out.println("写入完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Java IO 简介
IO也可以写作为 "
i/O
" ,也可以理解为In
和Out
,即输入与输出。所以,IO体系的基本功能就是: 读和写。IO流作用:读写设备上的东西,硬盘文件、内存、键盘、网络...
根据数据的走向,可分为:输入流,输出流。
根据处理的数据类型,可分为:字节流、字符流。
字节流和字符流的区别
- 字节流可以处理所有类型的数据,如MP3、图片、文字、视频等。在读取时。读到一个字节就返回一个字节。
在Java 中对应的类都以“Stream”结尾。
- 字符流仅能够处理纯文本数据,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。
在Java中对应的类都以”Reader“ 或 "Writer" 结尾。
多线程
进程:正在执行中的程序,其实就是应用程序在内存中运行的空间。
线程:进程中的一个执行单元,负责进程中的程序的允许,一个进程中至少要有一个线程。
一个进程中可以是有多个线程的,这个应用程序也可以称之为多线程程序。
可以实现多部分程序同时执行,专业术语称之为 并发
多线程的使用可以合理使用
CPU的资源,如果线程过多会导致降低性能。
CPU处理程序时,是通过快速切换完成的,在我们看来好像随机一样。
创建线程的两种方式:
继承Thread类
1. 定义一个类继承Thread
2. 重写run方法
3. 创建子类对象,就是创建线程对象
4. 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法
问题及回答
线程调用run方法和调用start方法区别:
- 调用run方法不开启线程,仅是对象调用方法。
- 调用start开启线程,并让jvm调用run方法在开启的线程中执行。
为什么继承Thread类?
- 继承thread类,因为thread类描述线程事物,具备线程应该有的功能。
为什么不只讲创建thread类的对象呢?
Thread thread = new Thread();
thread.start();
创建线程的目的是什么?
- 为了建立单独的执行路径,让多部分代码实现同时执行,也就是线程创建并执行需要给定的代码。(线程的任务)。
主线程的定义
主线程,该任务定义在main函数中,自定义线程需要执行的任务都定义在run方法中。
thread类中run方法内部的任务并不是我们所需要,只要重写run方法,既然Thread类已经定义了线程任务的位置,只要在位置中定义任务即可。所以进行了重写run方法动作。