1、封装
1、数据打包
2、访问控制
1、包
包的命名:所在组织的域名倒过来写
java对于所有出现在自己工程的类是按包管理的,没有建包时Java默认一个空包,
在另外一个类中引用不同包的类时必须引入包,引入包时一定在package包名称下面
import 包名称.子包名称.类名称; //手动导入包
import 包名称.字包名称.*; //由JVM自动加入加载所需要的类
1、访问控制
友元关系
公有
**public:**被public修饰的属性或方法在任意其他类其他位置都可以看见(访问或调用);
私有
**private:**只能在本类中调用的属性;
访问控制符可以修 饰类,方法,属性;
**package:**当不加任何访问控制修饰符时,默认为package,即只能在同包下面访问;
**protected:**在继承下可用,同包下也可用
任何位置 | 同包 | 继承 | 自己本类 | |
---|---|---|---|---|
public | 可见 | 可见 | 可见 | 可见 |
protected | 不可见 | 可见 | 可见 | 可见 |
default | 不可见 | 可见 | 不可见 | 可见 |
private | 不可见 | 不可见 | 不可见 | 可见 |
(1)Java里的对象和内存的关系JVM
Java的内存一定在Java虚拟机(JVM)中分的,Java内存分为五部分:(1)程序计数器,不起到任何存储的作用,里面只有一个行号计数器记录代码运行的行数,(2)栈,在栈里面存的是物理地址(3)堆(常量池也在堆里)(4)静态常量池(在一开始JVM就创建了0-127个数字)(5)方法区
1、堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象)
2、栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈)
3、方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap)
Java 的垃圾回收器(GC)主要针对堆区
对于回收方式:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
栈:只记录开始
堆:对象真正保存在堆里
堆区:只存放类对象,线程共享;
方法区:又叫静态存储区,存放class文件和静态数据,线程共享;
栈区:存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享;
程序计数器、虚拟机栈、本地方法栈
堆、方法区
类只是一个模板真正执行代码的是对象在执行.
Car c = new Car(1000);
c.fo(); //c通过栈找到堆
Car a = new Car(999);
//当a等于null时a通过找到的是null,此时代码会报出一个空指针的错误
a = null;
a.fo();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1KzDJzI-1617614085162)(E:\lanouJavaEE\笔记\堆.PNG)]
红色代表的是private,黄色代表的是不加访问控制时,只有在同包里的能调用,绿色代表的是public
当在线程时,栈是每个线程有一个,而堆是只有一个
2、常用类
1、String
String是一个字符的容器,既然是一个容器,他一定符合容器的常用操作,求长,定位,替换,
String的两种创建对象的方式,在java.lang包下
String str = "liguocheng";
String str1 = new String("liguocheng ");
此时比较的是str1地址的开始和str的开始
System.out.println(str == str1);
str的liguocheng在静态常量池中,str直接指向常量池内容;
str1创建在堆里,里面保存的liguocheng也是在常量池中,此时str1先找到栈,从栈找到堆,再指向常量池;
String str = "liguocheng";
String str2 = "liguocheng";
在常量池中出现的数据不会出现第二次;此时str2还是原先的liguocheng;再使用两个==做判断时,只有都在常量池中才相等,一个在堆里一个在常量池中不相等,
System.out.println(str == str2);
String str2 = new String("liguocheng ");
String str3 = new String("liguocheng ");
System.out.println(str3 == str2);
此时结果显示为false,new等于在堆里建了对象,两个对象所指地址不同
两个==对比的是地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BxOAfFzA-1617614085166)(E:\lanouJavaEE\笔记\1.PNG)]
字符串比较的时候一般比较的是内容,字符串用equals()方法来比较
String str = "liguocheng";
String str1 = new String("liguocheng ");
System.out.println(str .equals(str1));
四类八种基础型数据直接赋值都在常量池中,只要是常量池的内容就可以用==作比较
对于基础类型int比较时一定用基础类型来比较
2、基础数据类型的对象类型
(所有基础数据类型的对象类型都有两种赋值方式,直接赋值和创建对象赋值,直接赋值和创建对象赋值比较大小使用equals()作比较.一般用来作为辅助该种类的变量工具来使用)
对象数据类型的初始值 null
int(int比较大小时应该用基础数据类型int比较)
当不大于127时b和b1比较时指向同一个值,当大于127后,指向不同值
Interger的范围是[-128,127],在这个范围内比较大小,相等为true,超过范围为false
Integer b = 14;//Integer是int的对象类型
Integer b1 = 14;
Integer a = new Integer(14);
int c = 14;
Byte(类型的名字)
Byte b = 3;
Byte a = new Byte((byte)3); //因为Java默认为int,因此要类型转换
short
Short b = 3;
Short a = new Short((Short)3);
long
Long n = 2L;
Long a = new Long(3);
Float
Float a = 1.2f;
Float a = new Float(3.4f);
浮点型不能使用==比较,因为浮点数不能确定精确度,应该使用equals()比较
Double
Double a = 1.2;
Double a = new Double(3.4);
浮点型不能使用==比较,因为浮点数不能确定精确度,应该使用equals()比较
只要不存在浮动就可以使用==来比较
Char
character b = new character(‘b’);
character c = ‘c’;
character a = ‘c’;
System.out.println(ca);//c 和a可以用 比较
Boolean
Boolean c = new Boolean(flase);
Boolean b = flase;
Boolean a =flase;
System.out.println(ba);//无浮动是精确的可以用比较
基础数据类型的一些方法
将一个字符串转为相应的类型
int a = Integer.parseInt("55");//将一个是数字的字符串变为int型的数字,不能将十六进制转为int
Byte a = Byte.parseByte("55");
Long a =Long.parseLong();
Float a = Float.parseFloat();
Double a = Double.parseDouble();
Boolean a = Boolean.parseBoolean()
只有character没有parse方法,因为本身就是字符组成的,转的过程只要找到一个一个字符,转的过程都拿String来转的
charAt()从一个字符串中找到指定字符位置
String st = "a";
st.charAt(0);
2、compare()用来比较,用后一位减去前一位 大于0 证明前面大 小与0 后面大等于0一样大
System.out.println(Integer.compare(13,14);
3、bitCount()用来数位
System.out.println(Integer.bitCount(1);
4、decode()将十六进制转为int值
System.out.println(Integer.decode("0x65");
5、reverse()反转
00000000 00000000 00100000 00100000 8224
倒过来
00000100 00000100 00000000 00000000
6、MAX_VALUE 找到最大值
System.out.println(Integer.MAX_VALUE);
7、MIN_VALUE 找到最小值
System.out.println(Integer.MIN_VALUE);
8、MIN_NORMAL 自然数部分
字符串的一些常用方法
字符串的一些常用方法
1、char[] c = str.toCharArray();将字符串转为字符数组
2、split()按照指定的字符串堆字符串进行拆分
3、reverse()字符串反转
4、replaceAll()字符串替换
5、replace()字符串替换
String a = str.replace("r","e"); //替换,记住替换的不是原字符串,是返回一个新的对象a,字符串不可改变。
6、compareTo()比较大小按照字典序比较
6、concat() 字符串拼接
7、 sc.delete(3,5);//删除从第四位开始删除5-3两个
8、 sc.insert(2,"zhi");//从第2位开始插入zhi
9、//toUpperCase()将字符串变换大小写
System.out.println(str.toUpperCase());
10、将str与str1对比,一样返回true System.out.println(str.equalsIgnoreCase(str1));
11、contains()判断一个字符串中是否有包含指定的字符,输出truefalse
System.out.println(str.contains("ge"));//判断是否包含ge
12、startWith()判断是否是一个指定的字符串开始
13、endWith()判断是否以指定的字符串结尾
System.out.println(str.startWith("g"));判断是否以g开头
14、将字符串转为GBK形式
String str2 = "任大圣";
byte[] arra = str2.getBytes();
String str4 = new String(arra,"GBK");
System.out.println(str4);
15、inter()将字符串对象推入常量池
String str = new String("sfsa");
String s = str.inter();
StringBuffer()和StringBuilder
StringBuffer()和StringBuilder
StringBuffer用来操作String。StringBuffer里面内容可以改变
用StringBuffer与StringBuilder一样,区别只在前者线程安全,后者线程不安全
//将字符串拼接起来
//StringBuffer只有创建对象来赋值,创建一个StringBuffer类的对象
StringBuffer sc = new StringBuffer("ren");
sc.append("da");
sc.append("sheng");
System.out.println(sc);
//reverse倒置
字符串不可改变的特性导致直接操作字符串时会引起效率损耗问题,如两个字符串拼接,拼接完成会生成三个对象,五个字符串进行拼接,最后会出现9个对象 ,如果使用StringBuffer最后出现6个对象,尽量不要用+的方式进行字符串拼接(前提是常量池中没有字符串)
replace()和replaceAll()区别
replace的参数是char和字符串,即可以支持字符的替换,也支持字符串的替换;
replaceAll的参数是regex,即基于规则表达式的替换,比如:可以通过replaceAll("\\d", "*")把一个字符串所有的数字字符都换成星号;
如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串。
“\”在java中是一个转义字符,所以需要用两个代表一个
用replaceAll替换“\”为"\\",就要用replaceAll("\\\\","\\\\\\\\"),而replace则replace("\\","\\\\")。
作业 :
判断手机号是否合法
import java.util.Scanner;
public class Phone {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个手机号:");
String p = sc.next();
if(p.length()==11){
if(p.startsWith("13")||p.startsWith("15")||p.startsWith("17")||p.startsWith("18")||p.startsWith("19")){
try{
long f = Long.parseLong(p);
}
catch (Exception e){
System.out.println("不合法1");
}
System.out.println("合法");
}else{
System.out.println("不合法2");
}
}else{
System.out.println("不合法3");
}
}
}
1、水仙花数
100-999之间的数字,每一位如370按照以下算法33+73+0^3=370
找出100-999之间的水仙花数
public class Flower{
public static void main(String[] args) {
int num = 0;
for(int i = 0;i<1000;i++) {
int a = i/100;
int b = i/10%10;
int c = i%100;
if(a*a*a+b*b*b+c*c*c==i) {
System.out.println(i);
num++;
}
}
System.out.println("100-999之间的水仙花数有"+num);
}
}
2、回文字符串
abccba是回文字符串,上海自来水来自海上是回文字符串,abcd不是回文字符串
要求通过输入计算出该字符串是不是回文字符串
import java.util.*;
public class ReString{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
StringBuffer st = new StringBuffer(str);
String s = st.reverse().toString();
if(str.equals(s)) {
System.out.println("是");
}else {
System.out.println("不是");
}
}
}
}
3、统计输入的字符串里面,有多少个数字
import java.util.*
public class Total{
public static void main(String[] args) {
Scanner sc = new SCanner(System.in);
while(true) {
String str = sc.nexrLine();
int num = 0;
for(int i = 0;i<str.length();i++) {
if(str.charAt(i)>='0'&&str.charAt(i)<='9'){
num++;
}
}
Systrem.out.println("有"+num+"数字")
}
}
}
4、统计字符串里面,出现最长连续数字的长度是多少
dghjk1234k5679jj 最长连续数字是1234 数字全是0123456789
import java.util.*;
public class ContinuousNum{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
int num = 0;
for(int i = 0;i<str.length();i++) {
int max = 1;
int star = i;
int end = i;
if(str.charAt(i)>='0'&&str.charAt(i)<='9') {
while(i<str.length()&&str.charAt(i)>='0'&&str.charAt(i)<='9') {
end++;
i++;
}
for(int i = star;i<end-1;i++) {
if(str.charAt(i)-str.charAt(i+1)==-1) {
num++;
if(num>max) {
max = num;
}
}else {
max=1
}
}
}
}
System.out.println(num);
}
}
}
2、继承
extends
A extends B
是子类对父类的一个继承
父类/超类
public class Animal{
public String color;
public String type;
public void eat(){
}
}
子类/派生类
public class Dog extends Animal{
public String naem;
}
本类的公有方法可以调用私有属性,私有属性能不能继承是一个争论点。私有属性能继承,但是子类不能直接调用,可以通过其他操作间接访问父类中的私有成员,
同包下可以继承,当定义为public时在任何地方都可以调用
Java中,类范畴中,继承是单继承/链式继承,即一个子类只能继承一个一个父类。
Java只支持单继承,实现多重继承三种方式: (1)直接实现多个接口 (2)扩展(extends)一个类然后实现一个或多个接口 (3)通过内部类去继承其他类
static不是继承
this(动态的)指的是本类对象
super(动态的)指的是父类对象
区别点 | this | super |
---|---|---|
属性访问 | 访问本类中的属性,若本类无此属性则从父类中继续查找 | 访问父类中的属性 |
方法 | 访问本类中的方法,若本类无此方法则从父类中继续查找 | 直接访问父类中的方法 |
调用构造 | 调用本类构造,必须放在构造方法的首行 | 调用父类构造,必须放在子类构造的首行 |
特殊 | 表示当前对象 | 指的是父类对象 |
在继承中,
在子类中对父类中方法的覆写,其方法名称、参数列表、返回值类型必须全相同,访问控制可以更改,但是只能从小往大的改(若是往小的改会违反里氏替换原则)
当父类含有构造函数时,子类必须创建一个构造方法
父类
class Animal{
public String color;
public String type;
public void eat(){
System.out.println("会吃就是动物")
}
}
子类
calss Cat extends Animal {
public void eat() { //覆写父类中的方法
super.eat(); //调用父类的方法
System.out.println("吃鱼");
}
public void work(){
System.out.println("捉老鼠");
}
}
里氏替换原则:所有父类可以完成的动作子类都可以完成
Animal animal = new Cat();//animal声明的类型是一个动物的对象,给过来的类型是一个Cat
animal.work();//直接调用不可以,因为Animal中没有这个方法
((Cat)animal).work();//若调用必须调转类型
animal.eat();//可以调用eat方法因为Animal中有这个方法,但是实际上是Cat的对象调用的Cat的eat方法
构造方法不能被继承
子类创建之前必须先创建父类对象,创建子类对象必须先调用父类构造方法,再调用子类构造方法,
当父类中没有无参构造方法时,子类必须手动调用有参构造方法,
构造方法只能是动态的
父类
class Animal{
public String color;
public String type;
//父类构造方法
public Animal(String color,String type) {
this.color=color;
this.type = type;
}
public void eat(){
System.out.println("会吃就是动物")
}
}
子类
calss Cat extends Animal {
//子类构造方法
public Cat(String color,String type) {
super(color,type);
}
public void eat() { //覆写父类中的方法
System.out.println("吃鱼");
}
public void work(){
System.out.println("捉老鼠");
}
}
1、static(有可能考到)
静态内容在初始化的时候就被放进元数据区,静态内容一开始就存在,静态的内容放在元数据区内,在1.8版本以前叫永久代或持久代,静态东西先于对象存在而存在;
动可调静静不可调动,即动态可以调用静态的内容,反过来不行,
动态出现的时候静态一定有,静态出现的时候动态不一定出现;
静态可以修饰属性,方法,内部类,静态代码块(只要加载类就执行)
只要静态代码块被使用了其他的静态代码块都被使用了;
调用顺序:先是父类静态代码块再是子类的静态代码块然后是父类构造方法再是子类构造方法,在子类调用静态方法时父类的静态代码块先调用再是子类的最后是方法的
静态内部类不可以直接访问外围类的非静态数据,而非静态内部类可以直接访问外围类的数据,包括私有数据
2、final
final可以修饰属性,方法,类,成员、局部变量,形参
final修饰后变为常量,必须为其赋值,之后不会再被改变
final修饰后内存地址也不会再被改变
final修饰方法后,表示为最终方法,在继承中不能再被重写
final修饰类后,表示这个类不能再被继承
final修饰局部变量(临时变量)后,表示这个以后都不能再被修改
final int a =3;
final修饰引用变量,变量的引用(也就是指向的地址)不可变,但是引用的内容可以变(地址中的内容可变)
final修饰形参后,表示外部再传进来参数也不能改变形参
package fina;
public final class Human {
//final可以修饰属性和方法和类和局部变量和形式参数
//当使用final修饰类时,代表本类不能被继承,
//被final修饰的变量标识符变为常量
//当用final修饰时必须给变量一个初始值
//定死声明时的内存的地址
public final int a = 3;//此时开始a不再变化
public final String str = "hhh";
//StringBuilder里的内容可变但是地址不可变
public final StringBuilder sb = new StringBuilder();
//当final和static一起修饰属性代表是静态常量,不创建对象也能用
public static final float PI = 3.14f;
//常量方法,当final修饰方法时,代表本方法不能再被重写
//当static和final一起修饰方法时,代表本方法为静态常量方法不创建对象就能使用
//但是不能改变本方法
public static final void foo() {
System.out.println("sout");
}
public void test(final int a) {//用final修饰形参,表示形参不再改变,指针指向不能改变,即是一个确定了的指针指向,不能改变的值
//final修饰临时变量,从此时起b不再该变
final int b = 4;
}
}
3、abstract:(抽象类)
abstract可以修饰类和方法
普通的类没有能力来承载抽象方法,抽象类可以承载抽象方法
普通子类继承抽象父类时必须重写父类抽象方法,即父类中用abstract修饰的普通方法,当变为抽象方法后不能再有方法体,
如果子类也是一个抽象类,就没必要去重写抽象方法;
abstract不能和final一起使用;不能和static一起使用;
抽象类不能创建对象;
抽象类的构造方法不能拿来创建对象,是用来定义子类必须对父类的一些属性进行初始化。
当使用抽象类创建对象时,实际就会创建一个没有名字的类即匿名类,用的是父类的名字,创建的实际是匿名类的对象,匿名类只能使用一次。
抽象类规定所有子类模板
public abstract class plasticToy {
public abstract void play();
}
普通类和抽象类区别
普通类:可以放普通方法、属性、静态变量、常量,可以创建对象、可以有构造方法
抽象类:可以放抽象方法不能创建对象,其余能力与普通类一样,抽象类存在的价值让别人继承,抽象方法的价值让别人实现,是在规定所有子类模板。
4、interface:接口(仅仅是一个规范)
接口名字首字母一定是I;
public interface IUsb {
}
接口一定是公开的,这样接口才有存在的意义;一个接口就是一个.java文件。
特点:
1.接口的属性会默认为是公共的静态的常量(public static final)
2.接口的方法被默认为公共的抽象方法(public abstract),无方法体
在这abstract不能和static一起使用
vvoid test();
3.静态方法和默认方法(default)可以有方法体
//在接口中写一个静态方法必须有方法体
static void foo() {}
//接口中默认方法可以有方法体,1.8版本之前不可以,// 1.8版本之后可以,是因为引用了一个语法糖
default void ou() { System.out.println("nihao");}
非抽象类继承接口:必须实现接口中的所有抽象方法,其中
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。
5、对比
Java继承在类范畴下是单继承,多实现;在接口范畴中是多继承,没有实现;接口和接口之间只有继承的关系,接口和类之间是实现的关系,类和类之间是继承的关系。
普通类 | 抽象类 | 接口 | |
---|---|---|---|
本身实现 | 可 | 可 | 不可 |
单继承 | 可 | 可 | 不可 |
多继承 | 不可 | 不可 | 可 |
构造方法 | 有 | 有 | 没有 |
创建对象 | 能 | 不能 | 不能 |
属性 | 有 | 有 | PSF(public static final) |
普通方法 | 有 | 有 | default |
抽象方法 | 不可 | 可 | 可 |
简单的做个关于抽象类和接口的总结吧:
区别1:抽象类体现继承关系,一个类只能単继承。接口体现实现关系,一个类可以多实现。
区别2:抽象类中可以定义非抽象方法和抽象方法,子类继承后可以直接使用非抽象方法。接口的方法都是抽象的,必须由子类去实现。接口中的成员都有固定的修饰符。
区别3:抽象类有构造方法,用于给子类对象初始化。而接口没有构造方法。
特点1:抽象类不可以实例化,即不能用new创建对象。抽象类必须由其子类覆盖了所有的抽象方法后, 该子类才可以实例化,否则,这个子类也是抽象类。
特点2:抽象类abstract关键字不能和哪些关键字共存:
- final 因为final修饰的方法不能被继承。
- static因为类.方法(),此方法没有方法体,没有意义。
- private 因为抽象方法是要被子类覆盖的,加上private子类就不知道这个方法了。
特点3:接口中声明变量必须是final、public 、static的,接口中定义的方法都是abstract、 public的。接口里的数据成员必须初始化,且全是常量,不是变量。
特点4:接口是抽象类的 变体( 你没看错 ), 接口也可以通过关键字extends来继承其他接 口。格式如下所示:
class 类名称 implements 接口A,接口B{ //接口的实现}
interface 子接口名称 extends 父接口1,父接口2,...{}
作业:重复代码
导包在ma’ven上导
初始化过程:
1. 初始化父类中的静态成员变量和静态代码块 ;
2. 初始化子类中的静态成员变量和静态代码块 ;
3.初始化父类的普通成员变量和代码块,再执行父类的构造方法;
|
简单的做个关于抽象类和接口的总结吧:
区别1:抽象类体现继承关系,一个类只能単继承。接口体现实现关系,一个类可以多实现。
区别2:抽象类中可以定义非抽象方法和抽象方法,子类继承后可以直接使用非抽象方法。接口的方法都是抽象的,必须由子类去实现。接口中的成员都有固定的修饰符。
区别3:抽象类有构造方法,用于给子类对象初始化。而接口没有构造方法。
特点1:抽象类不可以实例化,即不能用new创建对象。抽象类必须由其子类覆盖了所有的抽象方法后, 该子类才可以实例化,否则,这个子类也是抽象类。
特点2:抽象类abstract关键字不能和哪些关键字共存:
- final 因为final修饰的方法不能被继承。
- static因为类.方法(),此方法没有方法体,没有意义。
- private 因为抽象方法是要被子类覆盖的,加上private子类就不知道这个方法了。
特点3:接口中声明变量必须是final、public 、static的,接口中定义的方法都是abstract、 public的。接口里的数据成员必须初始化,且全是常量,不是变量。
特点4:接口是抽象类的 变体( 你没看错 ), 接口也可以通过关键字extends来继承其他接 口。格式如下所示:
class 类名称 implements 接口A,接口B{ //接口的实现}
interface 子接口名称 extends 父接口1,父接口2,...{}
作业:重复代码
导包在ma’ven上导
初始化过程:
1. 初始化父类中的静态成员变量和静态代码块 ;
2. 初始化子类中的静态成员变量和静态代码块 ;
3.初始化父类的普通成员变量和代码块,再执行父类的构造方法;
4.初始化子类的普通成员变量和代码块,再执行子类的构造方法;