目录
[1. 类、对象、方法](#1. 类、对象、方法)
一、面向对象
1. 类、对象、方法
java作为一种面向对象思想语言,关注的焦点是类。
(1)类:具有相同特征的事物的抽象描述
而一类事物,其中必然有许多的属性,这些属性即为成员变量 (因为变量直接定义在类中,所以称为类的成员)这里我们需要注意,在类中定义的成员变量可以不赋默认值,系统会自动初始化默认值。
(2)对象: 类是一个抽象概念,因此我们不能拿来直接使用,这时我们就需要一个类的实例来实现。这种以类为模版,在内存中创造一个实际存在的例子就叫做对象。
模版:(以一个汽车Car类为例)
Car bwm = new Car();
Car ();类的构造方法,类中会自动提供;
new Car (); 使用 new 关键字创造一个具体的对象,存在内存中;
Car bwm: 创建一个 Car 类型引用变量。 Car 类的引用,就是以后可以用来指向 Car 对象的对象引用。
java
public class TestCar { //创建Car类的实例化对象bwm
public static void main(String[] args) {
Car bwm = new Car();
}
}
class Car{
}
(3)方法
- 构造方法
特点:
方法名与类名相同,没返回值,不要 void 修饰;
每个类都有一个默认的无参的构造方法,一旦自定义了参数,原来无参的就不存在了;
除非自定义的就是默认值。
java
public class Car {
String name; //成员变量
float price;
String color;
public Car(){//构造方法--无参
}
public Car(String a,float c,String b){//构造方法--有参
name = a;
price = c;
color = b;
}
- 成员方法(表示一种功能、行为)
java
public class Car {
public void run(){ //分别为访问权限修饰符、返回类型、方法名
System.out.println("汽车行驶"); //方法体
}
}
(4)方法重载
一个类中有多个名称相同的方法
如何在调用时区分同名方法: 通过方法的参数的个数,类型,顺序区分;
构造方法和成员方法都可以实现方法重载;
方法重载与返回值没关系。
(5)抽象类
一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类;
用 abstract 修饰,类中有抽象方法必是抽象类,抽象类不一定有抽象方法。
特点:
抽象类不能被创建对象,其他同普通类,可以有构造方法;
子类想继承抽象类,要么重写其所以抽象方法,要么该子类也定义为抽象类。注:
抽象类中的抽象方法,没有方法体用abstract 修饰
只定义方法,没具体实现
java
public abstract class Animal {
private String name;
private int age;
public Animal(){
}
public abstract void eat();//抽象方法
public void sleep(){
System.out.println("睡觉");
}
}
2.面向对象三大特征
(1)封装
封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是
通过该类提供的方法来实现对隐藏信息的操作和访问
封装的特点:
通过特定的方法访问
隐藏类的信息
方便加入控制语句
方便修改实现
java
package day3.fengzhuang;
public class Fz {
//封装案例1:成员变量设为私有权限,在其他类中不能直接访问
/*private String name;
private int age;*/
//解决方法:向外界提供一个公共方法来访问,可在方法中加控制语句,属性控制权掌握在类自己这里
public void setName(String name){
if (name.length()>2&&name.length()<6) {
this.name = name;
}
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
//封装案例2:构造方法私有化,外界不能随意调用
public Fz(){
}
//在类加载时,只创建了这一个对象,对外提供(类似于电脑的任务管理器窗口,不想让外界创建多个对象,不论点几次,只打开一个窗口)
static Fz f3 = new Fz();
//于是就将方法私有化
private Fz(){
}
//向外界提供获得此对象的方法
public static Fz getF3(){
return f3;
}
}
(2)继承
日常编码中,当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么,多个类中无需再定义这些属性和行为,只需要和抽取出来的类构成继承关系。(通过extends关键字实现)
优点:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了is-a的关系,为多态的使用提供了前提。
java
class Dog extends Animal{
//子类想继承抽象类,要么重写其所以抽象方法,要么该子类也定义为抽象类
@Override
public void eat(){
System.out.println("达到");
}
//这里是方法的重写,父类的功能不能满足子类的需求,进行方法重写。
/*已实现方法的参数、返回值要和抽象类中的方法一样*/
@Override
public int asd() {
return 0;
}
}
abstract class Cat extends Animal{//抽象类
}
public abstract class Animal {//猫类和狗类都属于动物类,他们都能吃饭,因此继承该动物类
private String name;
private int age;
public Animal(){//构造方法
}
public abstract void eat();
public abstract int asd();
public void sleep(){
System.out.println("睡觉");
}
}
(3)多态
- 所谓多态,即父类引用指向子类对象,从而产生多种形态
Animal dog = new Dog();
Animal cat = new Cat();
同一种事物,在不同时刻表现不同状态(两者之间必须存在继承关系)
- 两个时间段
1. 编译期:写代码时 类型是 Animal (父类类型)
2. 运行期:运行代码时 类型是子类类型
多态也称向上转型 将子类型转为父类型 ( 只能调用父类中的方法 )
用父类类型表示任意的子类类型对象,便于程序扩展
java
public class Test {
public static void main(String[] args) {
//原本创建对象 Dog dog = new DOG();
Animal dog = new Dog();
Animal cat = new Cat();
dog.eat(); //多态中成员方法的调用--编译看左边(父类),运行看右边(调用子类重写的方法)
cat.eat();
dog.show(); //静态成员方法的调用--编译运行都看左边(调的是Animal类的方法)
System.out.println(dog.num); //变量不存在被子类覆写的说法,只有方法可以--编译运行都看创建对象时等号左边(Animal类)
/*向下转型
父类引用仅能访问父类所声明的属性和方法,不能访问子类独有的属性和方法。
为了访问子类独有方法,用类似强制类型转化的方法
父类类型转为子类类型
*/
Dog d = (Dog) dog;
d.sleep();
}
}
- 向下转型
父类引用仅能访问父类所声明的属性和方法,不能访问子类独有的属性和方法。
为了访问子类独有方法,用类似强制类型转化的方法,使父类类型转为子类类型
java
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sleep();
Dog d = (Dog) dog;
d.sleep();
}
}
class Dog extends Animal{
int num = 50;
public void sleep(){
System.out.println("睡觉");
}
static void show(){
System.out.println("狗");
}
}
class Animal {
private String name;
private int age;
public void eat(){
System.out.println("动物吃");
}
//静态成员方法,不存在方法重写,因此调用时用的是父类方法
static void show(){
System.out.println("动物");
}
}
二、常用类
1.Object类
● Object类是所有Java类的祖先(根基类)。每个类都使用 Object 作为超类(父类)。所有对象(包括数组)都继承实现这个类的方法。
● 如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类
2.Array类
(1)equals方法
比较两个数组对象中元素是否相等。返回true或false
(2)copyOf方法
把原数组元素放到一个新数组中
(3)fill方法
用指定的值将指定数组每个元素填充
(4)toString方法
将数组元素内容拼接成字符串输出
(5)sort方法
对指定数组排序
(6)binarySearch方法
二分查找(前提是有序数组,或先进行数组排序),返回下标,返回负数表示未找到,或数组未排序
(7)compareTo 指定排序规则
java
public class Array3 implements Comparable<Array3>{
//一个类要排序,实现Comparable接口,指定一个排序方法(使所以的类使用同一种排序方法)例如本类,既可以用id来排序也可应用name
private int id;
private String name;
public Array3(){}
public Array3(int id,String name){
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Array3{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
//compareTo 指定排序规则
//用类中的某个属性作为排序规则
//此方法在sort()方法底层调用,判断大小
@Override
public int compareTo(Array3 o) {
return o.id-this.id;//这里自定义降序排序。整形比大小 前减后 大于0 等于0 小于0 默认升序
}
}
class TestArray3 {
public static void main(String[] args) {
Array3 a1 = new Array3(1,"张三1");
Array3 a2 = new Array3(2,"张三2");
Array3 a3 = new Array3(3,"张三3");
Array3 a4 = new Array3(4,"张三4");
Array3 a5 = new Array3(5,"张三5");
Array3[] array3s = new Array3[5];
array3s[0] = a1; //这里是乱序存放
array3s[1] = a5;
array3s[2] = a2;
array3s[3] = a4;
array3s[4] = a3;
Arrays.sort(array3s);//整形比大小排序格式
System.out.println(Arrays.toString(array3s));
}
}
其结果为:
3.基本数据类型包装类
java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面 向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设 计类时为每个基本数据类型设计了一个对应的类进表示,这样八个和基本数据类型对应的类统称为包装类.
(1) 包装类主要用途:
● 作为和基本数据类型对应的类类型存在。
● 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
java
public class IntegerDemo { //这里演示几个常见的方法
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.SIZE);
System.out.println(Integer.BYTES);
Integer integer = new Integer(10);
Integer integer1 = new Integer(20);
System.out.println(integer + integer1);
//静态方法(操作的只是传入的值,完成后返回)
System.out.println(Integer.toBinaryString(10));//二进制
System.out.println(Integer.toHexString(17));//16进制
System.out.println(Integer.toOctalString(9));//8进制
System.out.println(Integer.max(10,5));//比大小
System.out.println(Integer.compare(10,5));//比大小 大于返回1,等于返回0,小于返回-1
//非静态(操作的是对象包装的值)
System.out.println(integer.equals(integer1));//比相等
System.out.println(integer.compareTo(integer1));//比大小 大于返回1,等于返回0,小于返
}
}
(2)装箱和拆箱
● 装箱
自动将基本数据类型转换为包装器类型
装箱的时候自动调用的是Integer的valueOf(int)方法
● 拆箱
自动将包装器类型转换为基本数据类型
拆箱的时候自动调用的是Integer的intValue方法
java
public class IntegerDemo {
public static void main(String[] args) {
//int c = integer.intValue(); 自动拆箱,默认调用了 intValue()方法
int c = integer;
int d = 128;
//Integer x = Integer.valueOf(d); 自动装箱,默认调用valueOf()方法
Integer x = d;
}
}
4.String类
常见方法:
●获取功能
char charAt(int index)
int indexOf(String str)
int indexOf(String str,int fromIndex)
String substring(int start)
● 转换功能
static String valueOf(char[] chs)
String toLowerCase()
String toUpperCase()
String concat(String str)
Stirng[] split(分割符);
● 去除字符串两端空格
String trim()
5.StringBuffer类
我们如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。而StringBuffer就可以解决这个问题线程安全的可变字符序列。
常见方法:
● 添加功能
public StringBuffer append(String str)
public StringBuffer insert(int offset,String str)
● 删除功能
public StringBuffer deleteCharAt(int index)
public StringBuffer delete(int start,int end)
● 替换功能
public StringBuffer replace(int start,int end,String str)
● 反转功能
public StringBuffer reverse()
● 截取功能
public String substring(int start)
public String substring(int start,int end)
注:● StringBuilder类功能和StringBuffer功能完全一致 , StringBuffer是线程安全的。
6.Math类
Math.abs 绝对值
Math.sqrt 平方根
Math.pow(double a, double b) a的 b 次幂
Math.max(double a, double b)
Math.min(double a, double b)
Math.random() 返回 0.0 到 1.0 的随机数
Math.long round(double a) double型的数据 a 转换为 long 型(四舍五入)
7.Random类
产生随机数
8.Date类
● 日期转字符串
Date now=new Date();
myFmt.format(now);
● 字符串转日期
myFmt.parse("2018-02-10");
字符串日期格式与 指定格式必须一致
例如:String s = "2018-03-15";
new SimpleDateFormat("yyyy-MM-dd")
三、集合
为什么需要集合?因为数组的长度一旦规定就是固定不变的 ,而实际开发中,我们经常需要进行添加或删除数据操作,这样我们更倾向于一种能动态增长的容器 来存放数据,这就需要用到集合了。
1.Collection接口
(1)List接口
● List 中的数据对象有顺序 ( 添加顺序 ) 且可以重复。
- ArrayList(数组列表,数据以数组存放,连续空间,遍历和访问元素效率高)
常用方法:
add(E element)
add(int index, E element)
get(int index)
indexOf(Object o)
lastIndexOf(Object o)
remove(int index) 删除并返回指定位置元素
- LinkList(链表存储,插入、删除元素效率高)
常用方法:
add(int index,Object element)
addFirist(Object element)
get(int index)
removeFirst()
remove(int index)
- List接口三种遍历
java
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo4 {
public static void main(String[] args) {
/*
List 接口实现类/ List集合遍历方式,三种遍历
*/
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
//1. for 循环,允许修改元素,但要注意元素位置移动和索引改变
// 一旦遇到两个相同元素相邻,便会出现只能删除其中一个的情况
//这时还需要退位计数器
/* for (int i = 0; i < arrayList.size(); i++) {
if ("a".equals(arrayList.get(i))){
arrayList.remove("a");
i--;
}
}
System.out.println(arrayList);*/
//2. 增强for循环,循环遍历时不允许修改元素集合(添加,删除操作)
/*for (String s:arrayList){
if (s.equals("a")){
arrayList.remove(s);
}
arrayList.add("a");
arrayList.remove("c");
System.out.println(s);
}*/
//3. 迭代器遍历--获得集合对象的迭代对象
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()){
String s = iterator.next();//获取下一个元素
if (s.equals("a")){
iterator.remove();//删除元素
}
}
System.out.println(arrayList);
}
}
(2)Set接口
● Set 中的数据对象不可以重复。
- HashSet**(HashSet类中的元素不能重复,元素是无序的)**
①HashSet 添加元素时,如何判断元素是否重复:(已由开发者在函数内部实现,这里只是讲述原理) 如果只用equals比较内容,效率较低;
②在底层会调用hashCode()方法--Object中的hashCode()返回的是对象的地址(很显然我们不想比较这个);
③因此会调用类中重写的hashCode(),他返回的是根据内容计算的哈希值 遍历时,会先用哈希值进行比较,提高效率,但是哈希值会出现,内容不同,哈希值相同的情况;
④因此,在此基础上还要调用equals()比较内容,提高效率和准确度
- TreeSet**(可以给Set集合中的元素进行指定方式的排序。存储的对象必须实现Comparable接口)**
2.Map接口
Map接口共性:
①数据存储是 键,值(key,value) 的方式
②键不能重复,值可以一致
③可以通过键找到值
④一个键只能映射一个值
- HashMap
HashMap底层存储数据结构:
哈希表(数组)存储---方便查找
同一位置存储元素8个以内---链表存储
存储元素=8且哈希数组长度>64---链表转为红黑树存储(太长链表不好查询)
若哈希数组长度不满足要求,不会转为红黑树
数组使用率超过0.75后也会进行扩容
- TreeMap
①底层使用树形结构存储
②键可以排序
③键元素类型必须实现Compare接口,重写compareTo()方法
- Map遍历方式
java
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo3 {
public static void main(String[] args) {
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("a","aa");//添加一组键 值对
hashMap.put("q","qq");
hashMap.put("c","aa");
hashMap.put("b","bb");
hashMap.put("a","aa");
hashMap.put(null,null);
//拿到所有的值
Collection<String> values = hashMap.values();
System.out.println(values);
//map遍历方式
//1. 先拿到所有的键 遍历键 由键得到值
Set<String> keySet = hashMap.keySet();
for (String s: keySet){
System.out.println(s+":"+hashMap.get(s));
}
//2. 推荐使用
Set<Map.Entry<String, String>> entries = hashMap.entrySet();
for (Map.Entry entry:entries){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}