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.儿子不能比父亲惹更大的麻烦(子类的异常的类型不能是父类的异常的父类型)