Java笔记
UML
统一建模语言
面向对象三大特征
一.封装性
类的内部信息不能被外部程序直接访问
但是可以用该类提供的方法(Method)对隐藏信息进行操作和访问
(注意,private成员只是不能被直接访问)
封装步骤
1.修改属性的可见性:
改为private
2.创建公有方法:
getter方法/setter方法
(分别用于属性的读/写)
Mydate d = new MyDate(); d.setDay(31); d.setDay(d.getDay()+1);
3.在getter/setter方法中加入属性控制语句:
对属性值的合法性进行判断
(不懂,判断什么合法性?这条看着像硬凑上去的)
二.继承性(Inheritance)
表示关系常用:is-a
父类更通用(一般特性),子类更具体(自身特性)
想象一棵树
三.多态性
不同对象对于同一个方法实现不同的行为
实际操作
创建项目\(\rightarrow\)新建类 guagua.java\(\rightarrow\)编译\(\rightarrow\)得到guagua.class
一个类对应一个文件
package shipping.reports; import shipping.domain.*; import java.util.List; import java.io.*; pubilc class Guagua { private String salutation; Guagua(String S){ salutation = S; } public void guagua(String C) { System.out.println(salutation + " " + C); } //out 是 System 类的一个static属性,它的类型是PrintStream //PrintStream 是 java.io 包里定义的一个类 } public class TestGuagua { public static void main(String[] args){ Guagua hello = new Guagua("Hello"); hello.guagua("World"); } } //提供输入参数,该参数就存入字符串中args[]中 //
标记(token)
return 0 三个标记
return0 一个标记
词法分析器的"贪婪性"
j = i+++++i; j = i++ + ++i;
类型
默写一下基本类型?
boolean
char
byte(8),short(16),int(32),long(64) (bits)
注意一下,8 bits 代表 \(-2^7 to 2^7-1\)
整数型默认为int
float(32),double(64) (bits)
浮点数默认是double
String 是一个类
引用类型
Primitive Variable
byte x =7;
Referenve Variable
Dog myDog = new Dog();
"Java中唯一的对象引用字面值(literals)是null"
这句话的意思就是,如果现在我们要写一个引用类型,然后现在其实并没有什么要引用的东西,我们就直接写个null,但是不能写别的东西,比如123,321这种东西(C++貌似就可以)
String s = null;也可以
现在又讲到堆(Heap)和栈(Stack)
栈用来存指令,堆用来存实例;
对象实例在heap中进行分配,然后呢在stack中保存一个4字节的heap的内存地址(这一部分好好玩,和我想象的一样);
然后再来说一下,栈里到底存什么:
1.基本数据类型,也就是刚才默写的那些东西啦~;
2.指令代码:函数方法属于指令;
3.对象的引用地址;
4.常量.也就是final 量?
变量生命周期
1.成员变量
类被实例化的时候创建
没有赋值的话是会有默认值的
2.局部变量
静态成员变量的初始化要先于非静态成员变量
class F{ int x = 20;//被F的构造函数调用前,x被设置为20; static int y = 30;//在F被加载时设置为30; }
局部变量不会被自动赋值
等一下,赋值这个东西...
public class LocalVariable{ public static void main(String[] args){ String[] s = new String[2];//可以,初值为null String[] s;//不可以 System.out.println(s[0]); } }
方法参数(Method parameter)
1.定义传入方法的参数
2.当调用该方法时,新变量被创建,生命周期持续到方法结束
这一块不太懂,不知道这个方法参数应该怎么放
在那里写这个所谓的方法参数?方法参数指的具体是什么
3.类变量
即静态变量
一看就是,和类同生同灭
"无论有多少对象,类变量始终只有一个拷贝,被多个对象共享"
初始化方法和成员变量相同,对
final变量
这个东西跟const没设么区别
如果一个final变量是对一个对象的引用,其引用必须相同,但对象本身可以不同
什么意思,这句话?
引用一个对象,引用必须相同,什么意思
是指我本来指向了一个地址,然后现在那个地址里的对象都换了,但是地址必须还指向那里的意思嘛??
class Walrus{ int weight; Walrus(int w){ weight = w; } } class Tester{ final Walrus w1 = new Walrus(1500); void test() { w1 = new Walrus(1400); //不合法的 w1.weight = 1800;//合法的 } }
public void getValue(final int a){ a = 10;//wrong! } public void getValue(final Contract c){ c.hourSpanName = "aa";//right } 所以意思就是说,某类(并且是final)的里面的局部变量是可以被改变的 ...对吧?
数组
通俗易懂的一段话:
在java中数组是对象,比如int是基本型,但是int[]是对象
数组的声明没有创建数组对象,只创建了对数组对象的引用
数组元素所占用的内存是通过new或者初始化有系统动态分配的
数组具体怎么用我们就...先不说啦,感觉很简单
String[] a = new String[]{"x","y","z"}; int[] ages; ages = new int[]{1,2,3,4,5};
关于heap和stack
int a = 3;//stack memory int[] b = {1,2,3,4,5};//stack里面有int[]b的地址 //heap里面有1,2,3,4,5的内存
数组长度
int len = i.length;
用new创建的变量都是引用型变量
Shirt myShirt = new Shirt(); Shirt [] shirts = {new Shirt(),new Shirt(),new Shirt()}; 其中stack中存shirts和myShirt的地址 heap里面存shirts里面三个新的Shirt的地址,然后继续存它们的具体值,还有myShirt的具体值。(看图)
二维数组
一旦数组被创建,就不能修改长度(和C++一样)
但是可以写:
int Array[] = new int[6]; Array = new int[10];
运算符
instanceof 判断已给的对象是否是某个类或者是接口
等一下 接口到底是啥啊??
右移运算符
算术右移,有符号,>>
逻辑右移,无符号,>>>,最高位补0,只允许对int和long型,byte型会被扩展成int型
表达式类型
表达式中,char被扩展成int
隐式转换
基本类型转换
变宽转换是合法的,变窄转换是不合法的
引用转换
Oldtype x = new Oldtype(); Newtype y = x; //Oldtype 貌似是 Newtype的 子类
显示转换
强制转换导致信息损失,需要显示转换
long BigValue = 99L; int squashed = bigValue; int squashed = (int)bigValue; //所以显式转换就是...加“(类型)”??
public void doSomething(Employee e){ if(e instanceof Manager){ Manager m = (Manager) e; System.out.println("This is the magager of"+m.getDepartment()); } } //if you do not make the cast,an attempt to execute e.getDepartment() would fail,because the compiler cannot locate a method called getDepartment in the Employee class
$,abcd$可以作为java标识符 char[] a = {'1','2','3'}; char a[] = {'1','2','3'}; 都是合法的 (?)
基本
int random = (int)(Math.random()*10); Scanner input = new Scanner(System.in); int num = input.nextInt();
"switch(表达式)支持字串、枚举的语法糖"
“JDK1.5之前switch只支持byte,short,char,int”
“JDK1.5之后的自动拆箱,对应的这四种基础类型的封装类型类也同样支持Byte,Short,Character,Integer“
对不起看不懂,还反编译
算了...
switch支持String,其实是支持String的hash值
本质上是switch-int结构
并且利用equals方法来放置hash冲突的问题
最后利用switch-byte精确匹配
特殊循环控制
带标号的continue语句 和 带标号的break语句
这两个语句用来代替goto语句
outer: do{ statement; do{ statement; if(boolean expression){ break outer; } else if(boolean expression){ continue outer; } statement; } while(boolean expression); statement; } while(boolean expression);
使用增强的for循环
public void printElement(int[] list){ for(int element : list){ System.out.println(element); } } privete Map<String,Integer>stockMap = new HashMap(); for(Object i:stockMap.keySet()){ System.out.println("代号:"+i+",数量:"+stockMap.get(i)); }
类和对象
类
类包括:
字段field:对象包含的数据
方法
构造器(也就是构造函数)
初始化程序块
嵌套类(inner class)
类的修饰符
public:如果没写public 就只能在自己所属的包里访问
abstract:不能实例化
final:没有子类
类不可以是private和protected
包(package) 是用于区别类
java中的一个包相当于系统中的一个文件夹
protected 可以被子类的实例、同一个包内的所有类访问
构造器
其实就是构造函数
public class A{ private int x; public Thing(){ x = 233; } public Thing(int new_x){ x = new_x; } public int getX(){ return x; } public void setX(int new_x){ x = new_x; } }
如果不写构造器的话,系统自动创建
但如果写了带参数的构造器,系统不会帮忙创造一个不带参数的构造器
构造器之间的相互调用(使用this)
public class Hello{ String title; int value; public Hello(){ title+="Hello"; } public Hello(int value){ this();//必须在第一行调用,不能使用Hello(); this.value = value; } public Hello(String title,int value){ this(value); this.title += title; } }
初始化块
不知道在说什么,不想看
public class InitializationBlock{ private int x; static double d = 3.14; //非静态初始化块:在创建对象时执行(先于构造器); { x = 5; System.out.println("字段x = "+x); } //静态初始化块:仅在类被加载时执行一次; static{ int x = 10;//静态初始化块中的局部变量 System.out.println("局部变量x = "+ x); //静态初始化块中,this.x不可用 System.out.println("静态字段d = "+ d); } public static void main(String[] args){ new InitializationBlock(); } }
起名可以用字母,'**_','$**'开头
类的方法
静态方法
public class Count { private int serialNumber; private static int counter = 0; public static int getTotalCount() { return counter; } public Count() { counter++; serialNumber = counter; } } public class TestCounter { public static void main(String[] args) { System.out.println("Number of counter is " + Count.getTotalCount());//输出了0 Count count1 = new Count(); System.out.println("Number of counter is "+ Count.getTotalCount());//输出了1 } //应该直接用类名来调用静态方法 }
class SomeClass { static int i = 48; int j = 1; public static void main(String args[]) { i += 100; // j *= 5; } }
import java.awt.*; public class MyFrame extends Frame { MyFrame() { setSize(300,300); } public static void main(String args[]) { MyFrame theFrame = new MyFrame(); theFrame.setVisible(true); } } // 不知道写这一段东西是干嘛的
public class refValExample { static void Change(int[] pArray) { pArray[0] = 888; pArray = new int[] {-3,-1,-2,-3,-4}; System.out.println("方法内,第一个元素是:"+pArray[0]);//-3 } public static void main(String[] args) { int[] arr = {1,4,5}; System.out.println("调用方法之前,第一个元素是:"+arr[0]);//1 Change(arr); System.out.println("调用方法之后,第一个元素是:"+arr[0]);//888 } }
包装类
Java collection类中的元素必须为objects
List<Integer> a = new ArrayList<Integer>(); int i = 5; Integer itg = new Integer(i); Integer jtg = new Integer(6); int j = jtg.intValue(); //long转为Long long l = 8; Long lng = new Long(l); //Long转long Long gng = new Long(9); long g = gng.longValue(); Integer i1 = Integer.valueOf(42); Integer i2 = Integer.valueOf("42"); Boolean b1 = Boolean.valueOf(true); Boolean b2 = Boolean.valueOf("true"); Long n1 = Long.valueOf(42000000L); Long n2 = Long.valueOf("42000000L"); int i = Integer.parseInt("42"); boolean b = Boolean.parseBoolean("true"); double d = Double.parseDouble("3.14");
自动装箱的例子
List<Integer> li = new ArrayList<Integer>(); for(int i = 1;i<50;i++)li.add(i); //等价于li.add(Integer.valueOf(i));
public static int sumEven(List<Integer>li) { int sum = 0; for(Integer i:li){ if(i%2==0){ //等价:if(i.intValue()%2==0) sum += i;//等价:sum += i.intValue(); } } return sum; }
static
1.在类被加载的时候,就会加载被static修饰的部分
2.静态对象与实例对象相对
静态变量
是由static修饰的成员变量,又叫做类变量。说明这个变量属于类而不是属于对象
内存:则它在内存中只存在一份。JVM为静态变量分配一次内存空间。
实例变量
指这个变量是属于某个具体的对象的。
内存:创建几次对象,就有几次成员变量。
不要通过对象的方式去访问静态变量或者静态方法
静态不能访问非静态,非静态可以访问静态。(很常见的例子)
静态方法
不存在this关键字
静态是由类的加载而加载,this是由对象的创建而存在的。所以静态比对象优先存在。
多线程
分时利用CPU,也叫并发
每一次调用start()相当于:放入等待队列,等待CPU调度,处于就绪状态
方法run()称为线程体,它包含了执行线程的内容
只有用start()方法来启动线程,才能实现真正的多线程运行,
将run()方法当作普通方法的方式调用,程序仍然按照顺序进行.
实现多线程的两种方法
1.继承Thread类
Thread类在java.lang包中定义
一个类继承Thread类同时覆写了本类中的run()方法 \(\rightarrow\) 用start()启动线程 \(\rightarrow\)实现多线程操作
此方法的局限:一个类只能继承一个父类
$\rightarrow $Runnable 接口为非Thread子类的类提供了一种激活方式
2.实现Runable接口
package org.runnable.demo; class MyThread implements Runnable { private String name; public MyThread(String name) { this.name = name; } public void run() { for(int i=0;i<100;i++) { System.out.println("gua gua stand up!!"); } } }
实现run()方法,用new Thread(Runnable target).start()方法来启动
在使用Runnable定义的子类中没有start()方法,只有Thread类才有
public class Test { public static void main(String[] args) { Runner1 runner1 = new Runner1(); Runner2 runner2 = new Runner2(); Thread thread1 = new Thread(runner1); Thread thread2 = new Thread(runner2); //thread1.start(); //thread2.start(); thread1.run(); thread2.run(); } } class Runner1 implements Runnable { public void run() { for(int i=0;i<100;i++) { System.out.printlen("Runner1 : i"); } } } class Runner2 implements Runnable { public void run() { for(int i=0;i<100;i++) { System.out.printlen("Runner2 : i"); } } }
Packages
java.awt 图形,用户界面。
java.lang 提供对Java编程语言设计至关重要的类。
java.io 通过数据流、序列化和文件系统提供系统输入输出。
java.util 包含集合框架,旧集合类,事件模型,日期和时间设施。
Class
异常处理
java中异常被封装成了一个类
出现问题时,会创建异常类对象并且抛出异常相关信息
自定义的异常类
创建自定义的异常类需要继承自Exception类
并提供含有一个String类型形参的构造方法,该形参就是一场的描述信息,
可以通过getMessage()方法获得。例如:
public class NewException extends Exception{ public NewException(String s){//这个s就是自定义的精髓所在,想传啥传啥 super(s); } }
Throwable类是所有异常类的超类
Exception类继承自Throwable类
RuntimeException类是运行异常类,继承自Exception类,它以及它的子类只能在运行过程中存在
JAVA虚拟机
Java Virtual Machine
包括
一套字节码(Bytecode)(目标代码)指令集:
操作码(8位二进制,高位bits在低字节)+操作数
一组寄存器
若JVM定义较多的寄存器,则减少对栈和内存进行访问,提高运行速度
但如果JVM的寄存器比CPU的寄存器多,则JVM运行速度实际降低
JVM设置了4个常用的寄存器
pc 程序计数器:记录程序的执行
optop 操作数栈顶指针
frame 当前执行环境指针
vars 指向当前第一个局部变量的指针
optop,frame,vars用于记录指向Java栈区的指针
寄存器均为32位
一个栈
JVM模拟真实计算机,作为基于栈结构的计算机,Java栈是储存JVM存储信息的主要方法
栈框架
一个垃圾回收堆
一个存储方法域
Java数组被当作Object处理
try-catch
https://blog.csdn.net/qq_34427165/article/details/83929470
try { //可能出现异常的代码 } catch(异常类名A e){ //如果出现了异常类A类型的异常,那么执行该代码 } ...(catch可以有多个) finally { //最终肯定必须要执行的代码(例如释放资源的代码) }
代码执行的顺序:
1.try内的代码从出现异常的那一行开始,中断执行
2.执行对应的catch块内的代码
3.继续执行try catch结构之后的代码
1.儿子不能比父亲的本事大
2.儿子要比父亲开放
3.儿子不能比父亲惹更大的麻烦(子类的异常的类型不能是父类的异常的父类型)