一、final 关键字
final修饰属性、方法、类 二、接口 (interface、 implement)
1、什么是接口?
1)生活中的接口----USB接口2)面向接口编程3)接口存在意义? 2、接口怎么用?
简单总结:
1)接口定义 ( interface )2)接口实现 ( implements )3)接口使用实例---Animal CanCry() CanFly() 1)接口定义格式2)接口实现格式 3、接口特性?4、接口实例----Animal CanCry() CanFly()3、抽象类和接口区别
1)相同点:2)不同点: 4、抽象类和接口的关系? 三、数组
1、什么是数组?2、 数组的声明和创建
1)数组声明2)数组创建 3、 数组的访问和迭代
1)数组元素的访问2)数组迭代
for循环 和 增强for循环区别 4、数组排序
1)冒泡排序2)选择排序
一、final 关键字 final修饰属性、方法、类
修饰属性:修饰的属性是常量,必须直接赋值、或在构造方法中赋值
定义时直接赋值
static final int num =10; //常量不可变 ,所以直接写在模板上,故而 static final 推荐一起使用
定义时,没有赋值,在构造方法中赋值,在每个对象中都可以拥有一个常量
final int count ; //在构造方法中赋初值
public FinalDemo ( int count ){ // 每新建一个对象,就为属性赋值,赋值后,值就不能改变
this.count = count;
}
修饰方法:子类中不可以重写
修饰类 :不可以被继承, 不能修饰为抽象类或接口
package com.feifan.javaoop.day5;
public class FinalDemo{
// final修饰类 public final class String{}
// final修饰属性
// ctrl + 鼠标左键 进入底层查看String代码 private final char value[];
String s = "abc"; //字符串在底层是以数组形式存储 char [a,b,c] 字符串的值不能改变
//属性在定义时直接赋值
final int num = 10; //值不可以改变,推荐static final组合使用,整个内存中存一份
//属性在定义时没有为常量赋值,使用构造方法赋值,在每个对象中都可以拥有一个常量使用
final int count;//每创建一个对象时,为常量count赋值
public FinalDemo(int count) {
this.count = count;
}
public void test(){
//测试final修饰的num值能否改变
//num =100; 报错
new String("a");
new FinalDemo(10); //测试在定义时没有为属性赋值,通过构造方法赋值
new FinalDemo(20); //每新建一个对象时,给属性赋值,赋值后就不能改变
}
}
二、接口 (interface、 implement)
1、什么是接口?
顶层的功能定义 ,专注于功能设计,而不是实现,让其他类具体实现与抽象类相似,但有区别,接口实现多继承的逻辑用多态方法使用 1)生活中的接口----USB接口
USB接口本身没有实现任何功能
USB接口规定了数据传输的要求
USB接口可以被多种USB设备实现
只要有USB接口,就可以通过USB风扇,USB鼠标,U盘 具体实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dabXpqsb-1642950372831)(C:Users16431AppDataRoamingTyporatypora-user-imagesimage-20220123162439599.png)]
那怎么实现? 可以使用java接口来实现
编写USB接口---->通过需求设计方法 顶层 抽象的
实现USB接口---->实现所有方法
使用USB接口---->用多态方式使用 具体怎么用多态方式实现?
复习下多态:
多态使用场景: 喂不同动物吃,动物吃东西多态三个条件: 继承、重写、父类引用指向子类对象向上转型: 子类调用父类方法向下转型:父类调用子类自身特有的方法 2)面向接口编程
程序设计时:
- 关心实现类有何能力,而不关心实现细节面向接口的约定而不考虑接口的具体实现
java中一个类只能有一个父类,所以接口可以实现多继承的逻辑
2、接口怎么用? 简单总结: 1)接口定义 ( interface )[访问权限修饰符 ] interface 接口名称 [extends 其他接口名1,…其他接口名n]{
//1、静态属性 public static final
//2、抽象方法 public abstract
子类不能进行选择性地对所有抽象方法进行重写,要重写就得对所有抽象方法全部重写
//3、静态方法 public static void
//4、默认方法 public default void
子类可以选择是否对定义的默认方法重写
}
2)接口实现 ( implements )
[访问权限修饰符] class 类名 implements 接口1 ,接口2 …{ }
结合继承:
[访问权限修饰符] class 类名 extends 父类名 implements 接口1 ,接口2 …{ }
3)接口使用实例—Animal CanCry() CanFly() **接口是功能上的定义,**比如CanCry () CanFly() 抽象类除了功能定义还有类的成员变量,比如Animal 类中除了抽象方法还有成员变量 1)接口定义格式
接口——interface声明
接口中静态属性——默认public static final ,就是静态常量
接口中定义的属性用大写字母定义,比如:public static final PI =3.14;
接口中抽象方法——默认pubic abstract
接口中静态方法——接口可直接调用 public static
接口中默认方法——通过子类调用 public default
public interface MyInterface{ //interface 关键字定义类
int num; //所有属性默认为 public static final 静态常量
public void foo(); // 抽象方法是:public abstract
public static void test() {
//jdk8之后添加静态方法,接口可直接调用
}
public default void test1(){
//jdk8之后添加默认方法,通过子类调用
}
}
package com.feifan.javaoop.day5;
public interface MyInterface{
// public static final int NUM = 10; //必须赋值
int NUM = 10; //接口中定义的属性默认是静态常量
// public abstract void eat();
void eat();
void sleep();
//静态方法 接口自己调用
public static void test1(){
System.out.println("test1是接口中的静态方法,"+"接口中的属性NUM="+NUM);
}
//默认方法 是让子类重写,或让子类调用, 子类可以有选择地对默认方法重写
public default void test2(){
System.out.println("test2是接口中的默认方法,");
}
}
//----------------------------------------------------------------------
package com.feifan.javaoop.day5;
public class TestMyInterface {
public static void main(String[] args) {
System.out.println(MyInterface.NUM);//测试接口中的属性
MyInterface.test1();//测试接口中的静态方法,通过接口名调用
}
}
2)接口实现格式
类使用 implements关键字来实现接口
implements:实现[访问权限修饰符] class 类名 implements 接口1 ,接口2 …{ }结合继承: [访问权限修饰符] class 类名 extends 父类名 implements 接口1 ,接口2 …{ }
实现接口的 类命名 ,公认的写法后加 Impl
MyInterfaceImpl 前面:接口名,后面:Impl 表示接口类的实现 3、接口特性?
- 接口是隐式抽象的 ,声明接口时不需要abstract接口中的方法可以是抽象的、静态的、默认的接口中属性默认 public static final接口不是被类继承,而是被类实现接口不能实例化对象,无构造方法一个类可以实现多个接口与继承关系相似,接口与实现类之间存在多态一个接口能继承其他多个接口当类实现接口时,类要实现接口中的抽象方法,否则,类必须声明为抽象类
**接口是功能上的定义,**比如CanCry () CanFly()
**抽象类除了功能定义还有类的成员变量,**比如Animal 类中除了抽象方法还有成员变量
package com.feifan.javaoop.day5.InterfaceDemo;
public abstract class Animal{
private String name;
public Animal() {
}
public Animal(String name) {
this.name = name;
}
//动物的共性 抽象类
public abstract void eat();
public abstract void sleep();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.feifan.javaoop.day5.InterfaceDemo;
public interface CanCry { // 动物功能 接口
void cry();
}
package com.feifan.javaoop.day5.InterfaceDemo;
public interface CanFly { // 动物功能 接口
void fly();
}
package com.feifan.javaoop.day5.InterfaceDemo;
public class Bird extends Animal implements CanFly, CanCry {
@Override
public void eat() { // 继承和接口实现 都需要重写方法
}
@Override
public void sleep() {
}
@Override
public void fly() {
}
@Override
public void cry() {
}
}
package com.feifan.javaoop.day5.InterfaceDemo;
public class Dog extends Animal {
@Override
public void eat() { // Dog没有implements CanCry,所以不能使用多态
}
@Override
public void sleep() {
}
}
package com.feifan.javaoop.day5.InterfaceDemo;
public class Test {
public static void main(String[] args) {
Animal bird = new Bird(); //多态
CanFly b = new Bird();//接口也可以实现多态方法
CanCry c = new Bird();
// CanCry d = new Dog();//错误 Dog类没有implements CanCry,所以不能通过CanCry声明
}
}
3、抽象类和接口区别
想实例 ,抽象类Animal 中有抽象方法eat() , sleep() ,这些是动物共性 。
然后设计接口CanCry CanFly 是一些动物实例对象的功能 。
比如鸟能叫,鸟能飞,而狗能叫,但狗不能飞, Bird 类 implements CanCry CanFly , 那么新建一个Brid对象时,就可以使用多态,接口引用 指向 Brid对象,类似于继承中的多态,通过子类调用父类中的方法(向上转型、向下转型),就可以通过新建的 Brid对象 实现接口 。
**接口是功能上的定义,**比如CanCry () CanFly()
抽象类除了功能定义还有类的成员变量,比如Animal 类中除了抽象方法还有成员变量
1)相同点:- 都不能创建对象都可以表示多态性 (座位父类)
接口:
- 接口不能有构造方法不能有成员变量,只能有静态属性不能有成员方法,只能有静态方法,默认方法
- 抽象类能有构造方法能有成员变量
一个类只能继承一个父类 ---- 类和类
一个类可以实现多个接口 ---- 类和接口
一个接口可以继承多个接口 ----- 接口和接口
package com.feifan.javaoop.day5;
public class InterfaceA {
}
package com.feifan.javaoop.day5;
public class InterfaceB {
}
package com.feifan.javaoop.day5;
public class InterfaceC {
}
package com.feifan.javaoop.day5;
public interface MyInterface extends InterfaceB, InterfaceC{
}
package com.feifan.javaoop.day5;
public class MyInterfaceImpl extends Object implements MyInterface, InterfaceA{
@Override
public void eat() {
}
@Override
public void sleep() {
}
@Override
public void test2() {
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nELZC0Gj-1642950372834)(C:Users16431AppDataRoamingTyporatypora-user-imagesimage-20220123184643345.png)]
三、数组 1、什么是数组?数组是一组数据类型相同的数据集合数组是引用数据类型,即 数组是对象数组创建时必须有指定长度,创建后长度不可变,空间中内存是连续的数组可以存储基本数据类型,也可以存储引用数据类型
面试题:现有5MB大小内存空间,能否创建3MB大小的内存空间?
答案:不一定 , 5M空间中可能没有连续的3M, 数组必须是连续的内存空间
2、 数组的声明和创建 1)数组声明int [] m; //建议使用这种方式int n []; 2)数组创建
int [] a = new int[5];int [] a1 = new int[]{1,2,3,4,5};int [] a3 = {1,2,3,4,5};
package com.ffyc.javaarray;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {
int [] m; //建议使用这种方式
int n [];
//1、创建了数组对象,分配了空间,为空间分配了默认值,后期再对数组赋值操作
int [] a = new int[5];
long [] b = new long[5];
char [] c = new char[5];
boolean [] d = new boolean[5];
String [] s = new String[5];
System.out.println(a.length); //10
System.out.println(a); //[I@1b6d3586 输出的是地址,默认调用Objec类中的toString(),将对象以字符串形式展示
System.out.println(Arrays.toString(a)); //[0, 0, 0, 0, 0] toString 将数组内容以字符串形式输出
System.out.println(Arrays.toString(b)); //[0, 0, 0, 0, 0]
System.out.println(Arrays.toString(c)); //[ , , , , ]
System.out.println(Arrays.toString(d)); //[false, false, false, false, false]
System.out.println(Arrays.toString(s)); //[null, null, null, null, null]
//2、创建数组对象时,直接对数组内容进行填充
int [] a1 = new int[]{1,2,3,4,5};
System.out.println(a1);//[I@4554617c
System.out.println(Arrays.toString(a1));//[1, 2, 3, 4, 5] 将数组内容以字符串形式输出
//3、数组内容已知,就可以简化
int [] a3 = {1,2,3,4,5};
System.out.println(a3);//[I@74a14482
System.out.println(Arrays.toString(a3));//[1, 2, 3, 4, 5]
}
}
3、 数组的访问和迭代
1)数组元素的访问
数组名 [ index ] index 索引、下标索引从0开始索引最大值和数组长度差1 2)数组迭代
重复执行程序中的循环,直到满足某条件为止,亦称为迭代。
数组迭代 两种方式: for循环 、 增强for循环 for循环 和 增强for循环区别
for 循环有下标 ,可以对数组内按数组下标访问增强for循环 , 只能遍历出数组中的元素
package com.ffyc.javaarray;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.w3c.dom.ls.LSOutput;
public class Demo3 {
public static void main(String[] args) {
int [] c = {1,2,4,3,5};
System.out.println(c.length);//通过length属性获取数组长度
for (int i = 0; i < c.length; i++) {
System.out.println(c[i]);
}
//jdk5 之后 推出了增强for循环,如果只需要遍历,可以使用增强for
for(int t : c){
System.out.println(t);
}
}
}
4、数组排序
1)冒泡排序
比较两个相邻的元素,将值 大/小 的元素交换到右边
package com.ffyc.javaarray;
public class BubbleSortDemo {
// 冒泡排序
//比较两个相邻的元素,将值大/小的元素交换到右边
public static void main(String[] args) {
int [] a = new int[]{1,4,3,5,6};
System.out.println("数组长度为:"+a.length);
System.out.println("排序前:");
for( int t : a ){ //增强for循环
System.out.print(t+"t");
}
System.out.println("n"+"排序后:");
BubbleSortDemo bubbleSortDemo = new BubbleSortDemo();
bubbleSortDemo.BubbleSort1(a, a.length);
System.out.println("从小到大排序:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"t");
}
System.out.println("n"+"从大到小排序:");
bubbleSortDemo.BubbleSort2(a, a.length);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"t");
}
}
//冒泡排序 从小到大
public void BubbleSort1(int a[],int lenght){
for (int j = 0; j < lenght -1; j++) {
for (int i = 0; i < lenght -1; i++) {
if (a[i] > a[i+1]){
int temp = a[i+1];
a[i+1] = a[i];
a[i] = temp;
}
}
}
}
//冒泡排序 从大到小
public void BubbleSort2(int a[],int lenght){
for (int j = 0; j < lenght -1; j++) {
for (int i = 0; i < lenght -1; i++) {
if (a[i] < a[i+1]){
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}
}
}
数组长度为:5
排序前:
1 4 3 5 6
排序后:
从小到大排序:
1 3 4 5 6
从大到小排序:
6 5 4 3 1
思想是: 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
package com.ffyc.javaarray;
public class SelectionSortDemo {
public static void main(String[] args) {
int [] a = {1,5,4,7,0,2,5};
System.out.println("数组长度为:"+a.length);
//排序前
System.out.println("排序前:");
for(int temp : a){
System.out.print(temp+"t");
}
//排序后
System.out.println("n从小到大排序:");
SelectionSortDemo selectionSortDemo = new SelectionSortDemo();
selectionSortDemo.SelectionSort1(a, a.length);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"t");
}
System.out.println("n从大到小排序:");
selectionSortDemo.SelectionSort2(a, a.length);
for(int temp : a){
System.out.print(temp+"t");
}
}
//从小到大
public void SelectionSort1(int [] a, int length) {
for (int i = 0; i < a.length - 1; i++) {
int minIndex = i;
// 每一个元素都和剩下的未排序的元素比较
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[minIndex]) {
minIndex = j;//将最小数的索引保存
}
}
//经过一轮循环,就可以找出第一个最小值的索引,然后把最小值放到i的位置
swap(a, i, minIndex);
}
}
// 从大到小
public void SelectionSort2(int [] a, int length){
for (int i = 0; i < a.length - 1; i++) {
int maxIndex = i;
// 每一个元素都和剩下的未排序的元素比较
for (int j = i + 1; j < a.length; j++) {
if (a[j] > a[maxIndex]) {
maxIndex = j;//将最大数的索引保存
}
}
//经过一轮循环,就可以找出第一个最大值的索引,然后把最大值放到i的位置
swap(a, i, maxIndex);
}
}
public void swap(int [] a, int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
数组长度为:7
排序前:
1 5 4 7 0 2 5
从小到大排序:
0 1 2 4 5 5 7
从大到小排序:
7 5 5 4 2 1 0



