3_接口_修饰符_常用类

JavaSE_第三周

接口

概念
微观概念:接口是一种能力和约定
	接口的定义:代表了某种能力		
	方法的定义:能力的具体要求

宏观概念:接口是一种标准

经验:JAVA为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力

接口的语法

I.相当于特殊的抽象类,定义方式,组成部分,与抽象类类似

II.接口中只能定义公开静态常量

III.接口中只能定义公开抽象方法

IV.接口不是类

与抽象类的异同

I.相同:
1).可编译成字节码文件
2).不能创建对象
3).可以作为引用类型
4).具备Object中所定义的方法

II.不同:
1).所有属性都是公开静态常量,隐式使用public static final修饰
2).所有方法都是公开抽象方法,隐式使用public abstract修饰
3).没有构造方法,动态代码块,静态代码块

接口的规范

任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类是抽象类。

实现接口中的抽象方法时,访问修饰符必须是public .

接口引用

同父类一样,接口也可声明为引用,并指向实现类对象。

接口多态

不再关注具体的类型,而是关注行为

不同的引用类型,仅可调用自身类型中所声明的方法

常见的关系

常见的关系:
类与类:
单继承
extends 父类名称

类与接口:
多实现
implements 接口名称1,接口名称2,接口名称n

接口与接口:
多继承
extends 父接口1,父接口2,父接口n

注:Java中任意类都继承自Object(默认)

常量接口

将多个常用于表示状态或固定值的变量,以静态常量的方式定义在接口中统一管理,提高代码可读性

接口回调原理

接口回调:先有接口的使用者,后有接口的调用者

需要传递实例对象,背后实质传递的是实现类对象中的实例方法,实例方法的背后实质是方法的逻辑代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9GtuGfnS-1615107952167)(接口回调.png)]


/**
 * 接口/标准(排序)
 * 
 * 只有实现此接口的对象才可以排序
 *
 */
public interface Comparable<T> {

	/**
	 * 比较的方法:
	 * 	this与传入的stu对象进行比较
	 * @param stu 另一个学生对象
	 * @return 标准: 正数,负数,零
	 * 负数:this靠前,stu靠后
	 * 正数:this靠后,stu靠前
	 * 零:不变
	 */
	public int compareTo(T stu);
}
/**
 * 工具
 *
 */
public class Tool {

	/**
	 * 排序方法: 可以帮助任何类型的一组对象做排序
	 */
	public static void sort(Student[] stus) {
		
		for(int i = 0; i < stus.length - 1; i++) {
			
			Comparable currentStu = (Comparable)stus[i];
			
			int n = currentStu.compareTo(stus[i + 1]);//正数  this靠后 		接口的使用者	
			
			if(n > 0) {
				Student temp = stus[i];
				stus[i] = stus[i + 1];
				stus[i + 1] = temp;
			}
		}
	}
}
/**
 * 接口回调:先有接口使用者,再有接口实现者
 *	程序员
 */
public class TestCallback {

	public static void main(String[] args) {

		//需求:对一组学生对象排序
		Student[] students = new Student[] {
				new Student("tom",20,"male",99.0),
				new Student("jack",21,"male",98.0),
				new Student("annie",18,"female",100.0)};
		
//		java.util.Arrays.sort(students);//Error 没有排序规则
		
		//想要升序还是降序
//		int n = students[0].compareTo(students[1]);
		
		//工具调用者
		Tool.sort(students);//默认升序
		
		for(int i = 0; i < students.length; i++) {
			System.out.println(students[i].name + "\t" + students[i].score);
		}
	}

}

class Student implements Comparable<Student>{//接口的实现者
	
	String name;
	int age;
	String sex;
	double score;
	
	public Student() {}

	public Student(String name, int age, String sex, double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}

	public int compareTo(Student stu) {
		
		if(this.score > stu.score) {
			return 1;
		}else if(this.score < stu.score) {
			return -1;
		}
		return 0;
	}

}

接口的好处

接口的好处:

​ 程序的耦合度降低

​ 更自然的使用多态

​ 设计与实现完全分离

​ 更容易搭建程序框架

​ 更容易更换具体实现

关键字

interface

interface 接口名{}

注意:接口名的命名规则—需要遵循"大驼峰命名法",和类名的命名一致

接口的特点

1)接口中的功能是抽象方法,不能有方法体

2)接口不能实例化

3)如何实例化呢?

​ 通过" 接口多态"

​ 接口名 对象名 = new 子实现类名();

​ 接口是通过子实现类实例化----前提—这个子实现类是一个具体类!

格式
具体的子实现类
	开发中:  class 接口名+impl implements 接口名{

 	}
最终:接口的子实现类一定是具体类,否则没有意义!

接口比抽象类更抽象!
抽象类—不能实例化!(不能创建对象)
抽象类的实例化是需要通过子类进行实例化的
抽象类名 对象名 = new 具体子类名() ; 抽象类多态

接口中成员特点
成员变量----此时常量

		自定义常量:

				public static final int a = 10 ;//基本数据类型 :编译时期常量(不需要Jvm加载的)

				public static final Integer i = new Integer(10) ; //引用数据类型:运行常量(jvm需要加载的)
  

				存在默认的修饰符-----public static final (可以省略不写)

成员方法

		成员只能是抽象方法

		存在默认修饰符:public abstract (可以省略) *

构造方法:

		没有构造方法! 

方法的形式参数以及返回值问题的研究

方法的形式参数

		引用类型:

				数组:实际参数需要传递当前数组对象

				类:

					具体类:实际参数传递,需要该具体类对象(要么直接匿名对象,要么 具体类名 对象名 = new 具体类名();)

					抽象类:实际参数传递,需要该抽象类的子类对象(通过抽象类多态的形式 :该抽象类的子类对象(具体类)							或匿名内部类)

				接口:实际参数传递,需要该接口的子实现类对象(通过接口多态的形式:接口的子实现类对象或匿名内部							类)

方法形式参数:如果是引用类型(除过String),形式参数的改变会直接影响实际参数!

 方法的返回值是引用数类型

				类:

						具体类:方法需要结束,返回的是当前具体类型----有一个空间地址值(匿名对象/有名字对象 类名 对象								名 = new 类名();)

						抽象类:方法需要结束,返回的是当前抽象类的子类对象----定义一个子类继承抽象类或匿名内部类 

			接口类型:方法需要结束,返回的是当前接口的子实现类对象---定义接口的子实现类实现接口(接口多态)或匿						名内部类

面试题----接口和抽象类的区别

1)成员的区别
 抽象类:
    成员变量:可以是常量,也可是变量
    成员方法:可以是抽象方法,也可以是非抽象方法
    构造方法:存在的,有参构造/无参构造---给数据进行初始化
 接口:
 	成员变量:只能是常量
      存在默认的修饰符:public static final (可以省略)
    成员方法:只能是抽象方法
   	   存在默认的修饰符 : public abstract(可以省略)
    构造方法:
       不存在
 2)关系的区别
    类和类的关系:
       继承关系:extends
       只能支持单继承,不支持多继承,但是可以多层继承!
   
    类和接口的关系
       实现关系:implements  
       一个类可以实现多个接口---->也可以继承某个类的同时可以实现多个接口
    接口与接口的关系
       继承关系:extends
        既可以单继承,也可多继承
        
 3)设计理念的区别
    抽象类:存在继承关系,体现的是一种"is a"的关系
    接口: 提供的一种额外的功能,本身不具备的,只有实现了接口才具备这个功能,体现的一种"like a"的关系!

修饰符

状态修饰符

final:最终的,无法更改的!

  •           可以修饰类,当前类不能被继承
    
  •           可以修饰变量,此时这个变量是一个常量
    
  •           可以修饰成员方法,此时这个方法不能被重写!
    
静态修饰符

static: 共享(共用!)

  •              随着类/接口的加载而加载
    
  •              优先于对象存在  (不能this关键字)
    
  •              被static修饰 的成员变量,可以被多个对象共用
    
  •              被static修饰的,它的访问方法是 推荐--->使用类名/接口名.变量;/方法名();
    
抽象修饰符

abstract:抽象

  •       可以修饰类----抽象类(描述:现实世界事物中,比较概括性的东西)
    
  •       可以修饰成员方法---->抽象方法
    
  •                              可以在抽象类中使用
    
  •                              也可以接口中使用
    
权限修饰符

​ 在同一个包下的本类中 在同一个包下的子类(无关类中) 不同包下的子类中 不同包下无关类中

public Y Y Y Y

protected Y Y Y

默认修饰符 Y Y

private Y

开发中,优先使用public—访问权限足够大的

其次是protected---->我们自定义的时候很少写,一般都是在源码中

内部类

什么是内部类

一个类中定义另一个了类!

举例: 在类A中定义了一个类B,那么将类B称为类A的内部类,类A是当前类B的外部类

内部类的特点

​ 编译后可生成独立的字节码文件

​ 内部类中的成员可以访问外部类的成员,包括私有!

​ 外部类的成员访问内部类(成员内部类)中的成员方法,需要创建内部类对象来访问!

内部类的分类

成员内部类

静态内部类

局部内部类

匿名内部类

成员内部类

在类的内部定义,与实例变量实例方法同级别的类

外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象

当外部类和内部类存在重名属性时,会优先访问内部类属性

成员内部类不能定义静态成员

特点

1)它的成员可以访问外部类的成员,包括私有

2)测试类中,访问当前成员内部类中的成员方法

​ 前提条件:当前成员内部类:是非静态的!

​ 格式:

​ 外部类名.内部类名 对象名 = 外部类对象.内部类对象;

成员内部类中可以加入修饰符

为了保证数据的安全性,在成员内部类加入私有修饰符:private

在翻阅源码中–会有私有的成员内部类!

public class TestMemberClass {

	public static void main(String[] args) {

//		Inner in = new Inner();//Error 不能脱离外部类对象独立存在
		
		Outer out  = new Outer();
		
		//创建成员内部类对象(必须依赖外部类对象)
		Outer.Inner in = out.new Inner();
		
//		System.out.println(in.b);
		
		in.m2();
		
//		System.out.println(out.a);//Error 封装依旧有效,无法从外部直接访问

//		Outer.Inner.field;//Error 无法脱离外部类对象进行静态的调用
	}

}

class Outer{
	
	private int a = 10;
	
	//成员内部类,依赖外部类对象
	class Inner{
		
		int a = 20;
		
		/*static*/ String field = "abc";//成员内部类不能定义静态成员
		
		public void m2() {
			int a = 30;
			System.out.println("Inner -- m2()  " + a);//内部类可以访问自身的局部变量
			System.out.println("Inner -- m2()  " + this.a);//内部类可以访问内部类实例变量
			System.out.println("Inner -- m2()  " + Outer.this.a);//内部类可以访问外部类的实例变量
		}
	}
}
静态内部类

不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员

只能直接访问外部类的静态成员(实例成员需实例化外部类对象)

特点

静态的成员内部类中的成员方法(静态/非静态)只能访问外部类的静态的成员,否则报错!

非静态的成员内部类中不能出现静态的成员!

public class TestStaticClass {

	public static void main(String[] args) {

		//外部类的静态属性
		System.out.println(Outer.a);
		//外部类的静态方法
		Outer.m1();
		//创建静态内部类对象时,可直接通过完整名称进行创建
		Outer.Inter in = new Outer.Inter();//静态内部类的创建,不依赖外部类的对象
		
		//创建内部类对象后,访问实例属性和方法
		System.out.println(in.b);
		in.m2();
	
		//额外比成员内部类多了一个定义的内容(静态属性和静态方法)
		//通过外部类类名.内部类类名.内部类的静态属性
		System.out.println(Outer.Inter.field);
		//通过外部类的类名.内部类类名.内部类的静态方法
		Outer.Inter.m3();
	}

}

class Outer{
	
	static int a = 10;
	
	int c = 30;
	
	static class Inter{
		
		int b = 20;
		
		static String field = "abc";
		
		public void m2() {
			System.out.println("Inter--m2()");
//			System.out.println(c);
		}
		
		public static void m3() {
			System.out.println(a);
		}
	}
	
	static void m1(){
		System.out.println("Outer--m1()");
	}
	
}
局部内部类

定义在外部类方法中,作用范围和创建对象范围仅限于当前方法

特点

1)局部内部类的成员都可以访问外部类的成员,包括私有

2)外部类的成员要访问局部内部类中的成员,通过对象访问 内部类名 对象名 = new 内部类名() ;

JDK8+后新特性

局部内部类访问外部类当前方法的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final

public class TestLocalClass {

	public static void main(String[] args) {

		Outer out = new Outer();
		out.m1();
	}

}

class Outer{
	
	int a = 10;
	
	
	public void m1() {
		
		Printable pr = null;
		
		final String local = "Hello";//从JDK8+后,默认在此种情况下添加final关键字
		
		class Inter implements Printable{
			int a = 20;
			
			@Override
			public void print() {
				
				int a = 30;
				
				System.out.println("Inter -- m1()" + local);
			}
		}
		
		pr = new Inter();
		pr.print();
	}
}

interface Printable{
	public void print();
}
匿名内部类

没有类名的局部内部类

使用格式
new 类名/接口名(){
	//重写方法;
} ;

类名–可以是抽象类也可以是具体类(用的少)

位置----局部位置使用

匿名内部类的本质是什么?

本质就是继承了该抽象类或者是实现了该接口的子类对象

public class TestAnonymity {

	public static void main(String[] args) {

//		Animal a = new Dog();
//		a.eat();
//		
//		Animal a2 = new Animal() {
//			String furColor;
//			
//			public void eat() {
//				System.out.println("狗在啃狗头...");
//			}
//		};
//		
//		a2.eat();
//		
//		System.out.println(a2);
		
		Swimmable s1 = new Swimmable() {

			@Override
			public void swim() {
				System.out.println("会游泳的...");
			}
		};
		s1.swim();
		System.out.println(s1);
	}

}

//class Animal{
//	public void eat() {
//		System.out.println("动物在吃...");
//	}
//}
//
//class Dog extends Animal{
//	public void eat() {
//		System.out.println("狗在啃骨头...");
//	}
//}

interface Swimmable{
	public void swim();
}
使用范围

使用范围从小到大:匿名内部类 = 局部内部类 < 私有成员内部类 < 私有静态内部类 < 非私有成员内部类 < 非私有静态内部类

匿名内部类在开发中的使用

方法的形式参数如果是抽象类以及接口,实际参数如何传递
		如果是抽象类---需要该抽象类的子类对象
					1)要么定义具体的子类 ..
					2)要么使用抽象类的匿名内部类
					
			接口---->需要传递该接口的子实现类对象
					1)要么定义接口的子实现类
					2)要么使用接口的匿名内部类

方法的返回值如果是抽象类以及接口,如何返回?
			返回如果是抽象类,返回的需要该抽象类的子类对象
					1)要么定义具体的子类 ..  (匿名对象:  new 子类名() )
					2)要么使用抽象类的匿名内部类
			返回如果是接口类型,返回的需要该接口的子实现类对象
			
					1)要么定义接口的子实现类
					2)要么使用接口的匿名内部类

匿名内部类的面试题

//面试题补全代码:

       // 在控制台输出"helloworld"
interface Inter{
    void show() ;
}

class Outer{

    //补全代码:
    public static  Inter  method(){ //返回值是接口类型
            //返回的是该接口子实现类对象---->接口的匿名内部类
        return  new Inter(){

            @Override
            public void show() {
                System.out.println("helloworld");
            }
        } ;
    }
}
class InnerClassTest3{
    public static void main(String[] args){
        //给的代码
         Outer.method().show();
        //Outer.method()---->说明这个method方法是静态的  类名.方法名()

        //Outer.method().show();method方法调用完毕之后,是有返回值类型的方法----.show()---->接口中的方法
         //获取到接口的子实现类对象.show();
    }
}
外部类的this限定
//面试题

  //      请阅读代码,分别在控制台上输出30,20,10,补全代码

/**
 * 在内部类中,不存在继承关系
 * 变量名称一致的时候,遵循"就近原则"
 */
class Outer2{
    public int num = 10 ;
    //成员内部类
    class Inner2{
        public int num = 20 ;
        public void show(){
            int num = 30 ;
            //补全代码
            System.out.println(num);
            System.out.println(this.num);//代表是当前类对象的地址值引用
            System.out.println(new Outer2().num); //访问外部类中的num---new 外部类名().num;
            System.out.println("--------------------");
            //外部类的this限定
            //外部类名.this.变量名:访问外部类中的成员变量
            System.out.println(Outer2.this.num);

        }
    }
}
public class Test3 {
    public static void main(String[] args) {
        //给了代码
        Outer2.Inner2 oi = new Outer2().new Inner2() ;
        oi.show();

    }
}

API

学习Java中的常用类---常用的功能---在实际开发中都会用到

Application Programming  interface:应用程序接口文档

以后在开发中,学习各种各样的文档
	模拟百度地图定位系统-------百度地图---接口文档
	模拟人脸识别系统----- 百度Ai ----开发接口文档
	模拟微信分享功能----微信分享----接口文档

Object类

超类,基类,所有类的直接或间接父类,位于继承树的最顶层

任何类,如果没有书写 extends 显示继承某个类,都默认直接继承Object类,否则为间接继承

Object类中所定义的方法,是所有对象都具备的方法

Object类型可以存储任何对象

​ 作为参数可接受任何对象

​ 作为返回值可返回任何对象

常用方法

getClass()
public final Class<?> getClass(){}表示正在运行的是的类----->字节码文件对象(Class类对象)
返回引用中存储的实际对象类型
获取到的这个Class----class 包名.类名

Object类中的源码 getClass
	public final native Class getClass();
	native:本地方法 --- 非Java语言实现 (由Java调用非Java代码的接口)			                                       底层都是c或者是C++
    JNI:Java Native Interface:Java本地接口---- Java语言可以调用C语言
    
应用:通常判断两个引用中实际存储对象类型是否一致
hashCode()
public int hashCode(){}
返回该对象的十进制的哈希码值---由哈希表算出来的
哈希算法根据对象的地址或字符串或数字计算出来的int类型的数值
哈希码并不唯一,可保证相同对象返回相同哈希码,尽量保证不同对象返回不同的哈希码
toString()
public String toString(){}
返回该对象的字符串表现形式,通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。
可以根据程序需求覆盖该方法,如:展示对象的各个属性
equals()
public boolean equals(Object obj){} 指示其他某个对象是否与此对象“相等”
默认实现(this == obj),比较两个对象的地址是否相同
可进行覆盖,比较两个对象的内容是否相同

equals()方法覆盖步骤:
比较两个引用是否指向同一个对象
判断obj是否是null
判断两个引用指向的实际对象类型是否一致
强制类型转换
依次比较各个属性值是否相同

注:成员信息一样,认为应该是同一个人,所以要比较两个对象的内容是否相同,必须重写Object类中的equals方法,
 当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象(内容相等)必须具有相等的哈希码。
 
 ==和equals的区别:
 运算符号: 可以连接两个基本数据类型,基本数据类型比较的是两个数值是否相同!
 而如果==连接的是两个引用数据类型(对象),比较的是两个对象的地址值是否相同!
 equals方法:默认执行的是Object类中的equals方法,比较的是两个对象的地址值是否相同;
 如果重写了equals方法,比较的是两个对象的内容是否相同(成员变量信息是否一致)!
finalize()
当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象进入回收机制
垃圾对象:没有有效引用指向此对象时,为垃圾对象
垃圾回收:由GC销毁垃圾对象,释放数据存储空间
自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
手动回收机制:使用System.gc(),通知JVM执行垃圾回收
clone()
protected Object clone() throws CloneNotSupportedException
创建并返回此对象的一个副本
Object 类的 clone 方法执行特定的复制操作。
首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
注:所有的数组都被视为实现接口 Cloneable
通过clone方法复制 字段(属性)----浅克隆,针对对象的字段(属性)进行复制,不会创建新的对象

Scanner类

文本扫描器:Scanner ---- java.util.Scanner;
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
构造方法
public Scanner(InputStream source):创建一个文本扫描器,通过字节输入流读取输入的数据
				形式参数是一个抽象类---实际参数传递需要该抽象类的子类对象
成员方法
public boolean hasNextInt()
public boolean hasNextLine()
public boolean hasNextByte()
 ...
public boolean hasNextXXX()  :判断下一个数据录入的是否为xxx数据类型
public boolean haxNextLine();判断下一个数据是否为字符串类型


public xxx nextXXX() :接收数据的方法
public String nextLine()录入的是字符串类型
public class ScannerDemo {
    public static void main(String[] args) {

        //System---->有一个静态的字段in----标准输入流
        //static final InputStream in
        //字段的类型:InputStream
        InputStream inputStream = System.in ;

        //  public Scanner(InputStream source):
        Scanner sc = new Scanner(inputStream) ;

        //录入一个int类型数据
//        public int nextInt() //录入int类型数据
        /*System.out.println("请您录入一个int类型数据:");
        int num = sc.nextInt() ; //InputMismatchException:用户输入的类型和接收的类型不匹配,出现异常!
        System.out.println("您录入的数据是:"+num);*/

        //加入Scanner类提供的判断功能
        System.out.println("请您输入一个数据:");
        //public boolean hasNextXXX()
        if(sc.hasNextInt()){ //判断下一个录入的是否为int类型
            //true
            //使用int来接收
            int num =sc.nextInt() ;
            System.out.println("您录入的是一个数据为:"+num);
        }else if(sc.hasNextLine()){//判断下一个录入的是否为String
            String line =sc.nextLine() ;
            System.out.println("您录入的数据为:"+line);

        }else{
            System.out.println("对不起,没有提供这个录入的功能...");
        }
    }
}

键盘录入数据的细节
先录入int类型,在录入String类型:字符串数据被漏掉了
原因就是:回车符号的问题
      解决方案:
               1)使用Scanner中---public String next() 录入字符串   (非正式用法)
               2)在录入String类型的时候,可以创建一个新的Scanner对象

String类

String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。

字符串是常量;它们的值在创建之后不能更改。

构造方法
String()  :构造一个空字符序列
public String(byte[] bytes):将字节数组构造成一个字符串(解码的过程-平台默认的解码格式:UTF-8)
public String(byte[] bytes,int offset,int length):将一个部分字节数组构造成字符串
参数1:字节数组对象
参数2:指定的角标
参数3:指定的长度
 
public String(char[] value):将字符数组构造成字符串
public String(char[] value,int offset,int count):将字符数组的一部分构造成字符串
public String(String original):将某个字符串数据常量--构造成String对象
特点

字符串是常量;它们的值在创建之后不能更改。

形式参数如果是基本数据类型,形式参数的改变对实际参数没有影响

形式参数如果引用数据类型,形式参数的改变会直接影响实际参数! (除过String类型:作为形式参数和基本类型的效果一样)

public class StringDemo2 {
    public static void main(String[] args) {

        String s = "hello" ; //将常量赋值给变量s
        s+="qianfeng" ;
        System.out.println(s);//helloqianfeng
        System.out.println("----------------------------");

        int a = 20 ;  //实际参数
        int b = 30 ;

        System.out.println("a:"+a+",b:"+b);//a:20,b:30
        change(a,b) ;
        System.out.println("a:"+a+",b:"+b);//a:20 ,b:30

        System.out.println("===================================================");

        String str = "hello" ;
        System.out.println(str);//hello
        change(str) ;
        System.out.println(str);//hello

    }
    public static void change(String s){ //形式参数是引用类型:String=-->特殊的引用类型
        System.out.println(s);
        s+="worldjavaee" ;
        System.out.println(s);
    }



    public static void change(int a, int b) {//形式参数: 局部变量随着方法调用而存在,随着方法调用结束而消失
        System.out.println("a:"+a+",b:"+b);//a:20,b:30
        a = b ;
        b  = a+ b ;
        System.out.println("a:"+a+",b:"+b);//a:30,60
    }
}

判断功能
 public boolean equals(Object anObject):和指定的字符串进行比较(字符串重写了Object类中的equals方法):比较的是字符串内容是否相同
 public boolean equalsIgnoreCase(String anotherString):不区分大小写比较
 public boolean contains(String s/字符序列):判断是否包含指定的字符序列
 public boolean endsWith(String suffix):判断当前此字符串是否以指定的子字符串结尾
 public boolean startsWith(String prefix):判断当前此字符串是否以指定的子字符串开头
 public boolean isEmpty():判断此字符串是否为空
获取功能
  public char charAt(int index):获取指定索引处的字符
  public String concat(String str):将指定的字符串和此字符串进行拼接,获取一个新的字符串
  public int indexOf(String str):获取子字符串在当前字符串中第一次出现的索引值
  public int lastIndexOf(String str):获取子字符串在当前字符串最后一次出现的索引值
  public int length():获取字符串的长度
  public String substring(int beginIndex):从指定位置开始默认截取到末尾,获取当前字符串
  public String substring(int beginIndex,int endIndex):从指定位置开始截取到指定位置结束,包左不包右 						beginIndex,endIndex-1
字符串的遍历
public class StringDemo3 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您录入一个字符串数据:");
        String line = sc.nextLine() ;

        //遍历字符串:获取字符串中的每一个字符值:charAt()和length()相结合
        for(int x = 0 ; x < line.length() ; x++){
//            System.out.println(line.charAt(x));
            char ch = line.charAt(x) ;
            System.out.print(ch+" ");
        }

    }
}
转换功能
String类的转换功能
       public byte[] getBytes():编码过程(将能看懂的东西转换成看不懂的):将字符串转换字节数组
       public char[] toCharArray():将字符串转换成字符数组
       public String[] split(String regex):将字符串转换成字符串数组(分割/拆分功能)
       public String toLowerCase():将字符串转换小写
       public String toUpperCase():将字符串转换成大写
       public static String valueOf(int/long/float/double/boolean/Object):万能方法,
       将一些部分基本数据类型和引用类型转换成String
       
public class StringDemo {
    public static void main(String[] args) {

        //定义一个字符串
        String str = "hello" ;

        //public byte[] getBytes():编码过程(将能看懂的东西转换成看不懂的):将字符串转换字节数组
        byte[] bytes = str.getBytes();// 无参方法:平台默认的编码集: 当前idea:UTF-8
       // System.out.println(bytes);
        for(int x = 0 ; x < bytes.length ; x ++){
            System.out.println(bytes[x]); //字符串中的字符---寻找对应的ASCII码表中的值
        }
        System.out.println("--------------------------------------------------");

        // public char[] toCharArray():将字符串转换成字符数组
        char[] chars = str.toCharArray();
        for(int x = 0 ; x < chars.length ; x ++){
            char ch = chars[x] ;
            System.out.println(ch);
        }
        System.out.println("--------------------------------------------------");

        //public String[] split(String regex):将字符串转换成字符数组(分割/拆分功能)
        String s = "Java-C-Php-Go-R-Hadoop" ;
        String[] strArray = s.split("-");
        //遍历字符串数组
        for(int x = 0  ; x < strArray.length ; x ++){
            System.out.println(strArray[x]);
        }

        System.out.println("--------------------------------------------------");
        /**
         * public String toLowerCase():将字符串转换小写
         * public String toUpperCase():将字符串转换成大写
         */
        System.out.println("toLowerCase():"+str.toLowerCase());
        System.out.println("toUpperCase():"+str.toUpperCase());

        System.out.println("--------------------------------------------------");
        // public static String valueOf(int/long/float/double/boolean/Object):
        int i = 100 ;
        //int---- Integer(int类型的包装类类型)  ---String
        String result = String.valueOf(i);
        System.out.println("result:"+result); //"100"
        /*
        * 查看当前valueOf方法的源码
        * public static String valueOf(int i) {
                    return Integer.toString(i);  //Integer 类汇总的public static String toString(int i)---静态功能
         }
        * */


    }
}

替换功能
 替换功能
       String replace(char oldChar, char newChar)
比较功能
 public int compareTo(String anotherString)按字典顺序比较两个字符串
 
 String类的compareTo(String anotherString)按照字典顺序比较,如何计算的
		两个字符串进行比较(字典顺序)
		s1,s2
		1)将s1,s2分别转换成字符数组,获取这个两个长度:len1,len2
		2)获取两个字符数组中长度的最小值 通过Math.min(len1,len2) ;----int lim
		3)分别将字符数组的元素进行初始化: 
		   char v1[] = {'元素1','元素2'...};
		   char v2[] = {'元素1','元素2'....} ;
		   
		4)定义统计变量k
		while(k<lim){ //k 从0开始
			//获取第一个字符数组中的第一个元素 
			char c1 = v1[k] = v1[0] = '元素1';
			char c2 = v2[k] = v2[0] = '元素1' ;
				//c1和c2相等,继续判断,继续判断第二个字符是否一致,依次这样,
				(如果都一致,条件不成立)while循环结束
			
			if(c1!=c2){
				return c1 -c2 ;//字符对应的ASCII码表的值相减
			}
			k++;
		}		
		
		5)return len1-len2;

其他功能
去除两端空格
public String trim()

面试题

1.数组中有没有length(),字符串中有没有length(),集合中有没有length()方法?
	数组中没有length方法的,获取数组长度 :length属性
 		 arr.length;
	String类中:length() :获取字符串中的字符的长度
 	集合中:没有length() : 获取集合的元素数:size()
2.String s = "hello" 和 String s  = new String("hello") 分别表示什么?分别创建了几个对象?
 	都是表示创建字符串对象,里面内容为hello
 	开发中书写字符串对象---String 变量名 =;
 	前者:在常量池中开辟空间地址,创建一个对象---直接在常量池中操作
 	后者:在格式上,是在堆内存中创建空间的,并且指向的常量标记"hello"
          两个对象:堆内存中要new,另一个还要指向常量标记---常量池的空间地址
          从内存角度考虑:使用前者优于后者,后者开销资源大,浪费内存空间!
3.看程序,写结果
public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = "hello" ;
        String s2 = new String("hello");
        System.out.println(s1==s2);//false
        System.out.println(s1.equals(s2));//true

        System.out.println("------------------------");

        String s3 = "hello" ;
        String s4 = "hello" ;
        System.out.println(s3==s4);//true
        System.out.println(s3.equals(s4));//true
        System.out.println("------------------------");
        String s5 = new String("hello") ;
        String s6 = new String("hello") ;
        System.out.println(s5==s6);//false
        System.out.println(s5.equals(s6));//true
    }
}
4.看程序,写结果
==和equlas的区别:
	字符串常量相加和字符串变量相加的区别
	字符串常量相加---先相加,然后在常量池中找是否存在这个常量,如果存在,直接返回常量池中的该地址值;
 					如果不存在,在常量池中开辟空间
 	字符串变量相加----先开辟空间,然后对结果----拼接----新的字符串变量(== 考虑其地址值)
public class StringDemo3 {
    public static void main(String[] args) {
        String s1 = "hello" ;
        String s2 = "world" ;
        String s3 = "helloworld" ;

        System.out.println(s3 == (s1+s2));//false
        System.out.println(s3.equals(s1+s2))//true
        System.out.println(s3 == "hello"+"world") ;//true
        System.out.println(s3.equals("hello"+"world")) ;//true
    }
}

 5. 面试题
       String s1 = "hello" ;
       String s2 = "hel" ;
 
       这两个字符串按照字典顺序比较的时候,值是多少呢?
 
public class StringTest3 {

    public static void main(String[] args) {
        String s1 = "hello" ;
        String s2 = "hel" ;
        String s3 = "abc" ;
        String s4 = "hsbc" ;

        System.out.println(s1.compareTo(s2));//5-3 = 2
        System.out.println("-----------------------");
        System.out.println(s1.compareTo(s3));//7
        System.out.println(s1.compareTo(s4));//-14
    }
}

编码和解码

/**
 *
 * 编码和解码的使用 ------ 后期IO流会用到!
 *
 * 中文存储的时候:utf-8:一个中文对应三个字节
 *                  gbk:两个字节
 *
 *                  里面第一个字节一定是负数!
 
		编码:String----byte[] 字节数组
				getBytes()--->byte[]
		解码:byte[]----String: 
				String类的构造方法:
				String(byte[] bytes)
 *
 */
public class StringDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {

        //定义一个String
//        String s = "abc" ;
        String s = "我爱中国" ;
        //编码:String---byte[]
//        public byte[] getBytes():默认平台编码集 进行转换 (UTF-8)
//        byte[] bytes = s.getBytes("GBK");
        byte[] bytes = s.getBytes();
//        System.out.println(bytes);

        //Java中提供了一个工具类:Arrays
        //里面的功能都是静态的功能:public static String toString(byte[] a):将数组转换成字符串 : 字符数组中的:ASCII码表中的值
        System.out.println(Arrays.toString(bytes)); //[97,98,99]
        //[-26, -120, -111, -25, -120, -79, -28, -72, -83, -27, -101, -67] :utf-8格式
        //[-50, -46, -80, -82, -42, -48, -71, -6]:gbk格式

        System.out.println("--------------------------------");

        //解码
//        String(byte[] bytes) :通过字节数组构成成字符串成
//        String result = new String(bytes,"GBK")  ; //gbk解码
        String result = new String(bytes)  ; //utf-8解码
        System.out.println(result);

    }
}

可变长字符串类

StringBuffer:可变长字符串 JDK1.0提供,运行效率慢,线程安全

StringBuilder:可变长字符串,JDK5.0提供,运行效率快,线程不安全

StringBuffer类

线程安全的可变字符序列------ 字符串缓冲区

线程安全---->意味着 “同步操作” ------ >执行效率低

线程不安全----->意味着 “不同步” -------执行效率高

构造方法
StringBuffer() :无参构造方法 :构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
  public StringBuffer(int capacity):构造一个字符串缓冲区,指定容量大小
  public StringBuffer(String str):构造一个带内容的字符串缓冲区:字符串的初始容量为 16 加上字符串参数的长度
  public int capacity():获取容量大小
  public int length():获取字符串长度
添加功能
public StringBuffer append(xxx);将任意类型的内容追加到此序列中(字符串缓冲区中)
public StringBuffer insert(int offset,String xxx):在指定位置处插入指定的元素
删除功能
public StringBuffer deleteCharAt(int index):删除指定位置处的字符序列,返回值是StringBuffer本身
public StringBuffer delete(int start,int end):从指定位置删除到指定位置结束的字符序列(包含start位置,结束到end-1),返回值自己本身
替换功能
public StringBuffer replace(int start,int end,String str)
从指定位置处开始到end-1,使用str字符进行替换,返回StringBuffer本身
反转功能
public StringBuffer reverse():将缓冲区中的字符串进行反转,返回的StringBuffer本身
截取功能
public String substring(int start):从指定位置开始截取,默认截取到末尾,返回值是新的字符串
public String substring(int start,int end):从指定位置开始截取到end-1的位置,返回值是新的字符串
String和StringBuffer之间的相互转换
String----StringBuffer

		方式1:
				StringBuffer的有参构造方法
				StringBuffer(String str)
		方式2:
				StringBuffer的无参构造方法+添加功能:append(xx)
				StringBuffer sb = new StringBuffer() ;
				sb.append(指定的字符串) ;
				
				
StringBuffer---String

		StringBuffer buffer = new StringBuffer("javaee");
		//方式1:利用String类型的有参 构造方法
		String(StringBuffer buffer)
		String s = new String(buffer) ;
		
		//方式2:
		StringBuffer的toString的方法进行转换
		String s2 = buffer.toString() ;
String与StringBuffer作为方法形参的区别
  String作为形式参数(是一种特殊引用类型)的 特点:
          形式参数的改变不会直接影响实际参数,它和基本数据类型作为参数是一样的!
 
  StringBuffer作为形式的特点:
           形式参数改变会直接影响实际参数,和引用类型作为形式参数一样的
String与StringBuffer的区别
	String:字符串是常量,一旦被赋值,其值不能被更改
	String作为形式参数,形参的改变不会影响实际参数,它和基本类型作为形式参数效果是一样的
	StringBuffer:线程安全的可变字符序列
				线程安全的类----->同步的----执行效率低,
				单线程程序中(只考虑执行效率)使用StringBuilder替代StringBuffer
	StringBuffer作为形式参数,形参的改变会直接影响实际参数!
StringBuffer和数组的区别
两个共同点:都是"容器"
	数组:只能同一种数据类型的元素, 数据类型必须一致的!
	    数据类型:既可以存储基本数据类型,也可以存储引用数据类型
	
	StringBuffer: 字符串缓冲区 --->存储的可变的字符序列,
				存储是字符串数据(字符串本身由很多个字符组成的)
				线程安全的类----同步的----执行效率低 (单线程程序中,使用StringBuilder去替代StringBuffer)
StringBuffer和StringBuilder的区别
两个都是字符串缓冲区
	StringBuffer: 线程安全的类---同步的-----执行效率低
			StringBuffer和StringBuilder具有相互兼容的api
			StringBuffer里面的所有的成员方法几乎都有一个关键字:synchronized:同步锁!(互斥锁)
			
	StringBuilder:线程不安全的类---不同步的---执行效率高
	单线程中:StringBuilder去替代了StringBuffer,多线程环境中,优先使用的StringBuffer!
题目
指定一个数组,静态初始化了,将int类型数组,拼接成字符串数据

import java.util.Arrays;

/**
 * 需求:
 *      指定一个数组,静态初始化了,将int类型数组,拼接成字符串数据
 *      [元素1, 元素2, 元素3]
 *      int[] arr = {11,22,33,44,55} ;
 *      使用功能改进: (两种方式)
 *              结果: String类型
 *
 */
public class StringTest {
    public static void main(String[] args) {

        //创建一个数组,静态初始化
        int[] arr = {11,22,33,44,55} ;
        String result = arraytoString(arr);
        System.out.println("result:"+result);
        System.out.println("-------------------------------");

        //如果题意没有要求自己使用功能,那么直接使用Arrays工具类toString//方式2
        String result2 = Arrays.toString(arr);
        System.out.println("result2:"+result2);
        System.out.println("-------------------------------");

        //利用StringBuffer的append的追加
        String result3 = arrayToString2(arr);
        System.out.println("result3:"+result3);


    }

    //方式3
    public static String arrayToString2(int[] arr){
        //创建一个字符串缓冲区
        StringBuffer sb = new StringBuffer() ;
        sb.append("[") ;
        //遍历数组
        for(int x =0 ; x < arr.length ; x ++){
            //判断
            if(x == arr.length-1){
                sb.append(arr[x]).append("]") ;
            }else{
                sb.append(arr[x]).append(", ") ;
            }
        }
        return sb.toString() ;
    }

    //ctlr+alt+m:抽取方法
    //使用功能改进
    public static String arraytoString(int[] arr) {
        //定义一个字符串:空字符串
        String result = "" ;
        //拼接做中空号
//        result.concat("[") ; //拼接功能
        result += "[" ;
        //遍历数组
        for(int x = 0 ; x < arr.length ; x ++){
            //判断是否x是最大索引值
            if(x == arr.length-1){
                result += arr[x] ;
                result += "]" ;

            }else{
                result += arr[x] ;
                result +=", " ;
            }
        }
        return result;
    }
}

键盘录入字符串,将字符串反转,使用功能改进

import java.util.Scanner;

/**
 * 需求:键盘录入字符串,将字符串反转,使用功能改进
 */
public class StringTest2 {
    public static void main(String[] args) {

        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您录入一个字符串数据:");
        String line = sc.nextLine() ;

        //调用
        String result = reverse(line);
        System.out.println(result);
        System.out.println("------------------------------");

        String result2 = reverse2(line);
        System.out.println(result2);

    }

    //方式2:利用StringBuffer的反转功能
    public static String  reverse2(String s){
        //分别走:创建一个字符串缓冲区对象
        /*StringBuffer sb = new StringBuffer() ;
        //追加
        sb.append(s) ;
        //反转
        sb.reverse() ;
        return sb.toString() ;*/

        //一步走
        return new StringBuffer().append(s).reverse().toString() ;


     }

    //方式1:将字符串转换成字符数组
    public static String reverse(String s){
        //将字符串转换成字符数组
        char[] chs = s.toCharArray();
        //定义一个空串
        String result = "" ;
        //遍历字符数组
        for(int x = chs.length-1; x >=0 ; x --){
            result+=chs[x] ;
        }
        return result ;

    }
}

   //判断是否x是最大索引值
        if(x == arr.length-1){
            result += arr[x] ;
            result += "]" ;

        }else{
            result += arr[x] ;
            result +=", " ;
        }
    }
    return result;
}

}


###### 键盘录入字符串,将字符串反转,使用功能改进

```java

import java.util.Scanner;

/**
 * 需求:键盘录入字符串,将字符串反转,使用功能改进
 */
public class StringTest2 {
    public static void main(String[] args) {

        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您录入一个字符串数据:");
        String line = sc.nextLine() ;

        //调用
        String result = reverse(line);
        System.out.println(result);
        System.out.println("------------------------------");

        String result2 = reverse2(line);
        System.out.println(result2);

    }

    //方式2:利用StringBuffer的反转功能
    public static String  reverse2(String s){
        //分别走:创建一个字符串缓冲区对象
        /*StringBuffer sb = new StringBuffer() ;
        //追加
        sb.append(s) ;
        //反转
        sb.reverse() ;
        return sb.toString() ;*/

        //一步走
        return new StringBuffer().append(s).reverse().toString() ;


     }

    //方式1:将字符串转换成字符数组
    public static String reverse(String s){
        //将字符串转换成字符数组
        char[] chs = s.toCharArray();
        //定义一个空串
        String result = "" ;
        //遍历字符数组
        for(int x = chs.length-1; x >=0 ; x --){
            result+=chs[x] ;
        }
        return result ;

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值