java
菜鸟工具——java在线运行
https://c.runoob.com/compile/10/
Java开发注意事项
DOS(Disk Operating System 磁盘操作系统)
常用dos命令:
换行快捷操作
ctrl+d
double+Sting类型结果是String
负小数取模
取模支持对负数进行运算,结果与被膜数的符号一致
java中int不能自动转化为boolean
构造器的复用
“`class A04{
String name;
int age;
double salary;
String pos;
boolean sex;
public A04(String name,int age){
this.name=name;
this.age=age;
<pre><code>}
public A04(double salary,String pos,boolean sex){
this.sex=sex;
this.salary=salary;
this.pos=pos;
}
public A04(String name,int age,double salary,String pos,boolean sex){
this(salary,pos,sex);
this.age=age;
this.name=name;
}
public void show_message(){
System.out.println(name);
System.out.println(age);
System.out.println(salary);
System.out.println(pos);
System.out.println(sex);
}
</code></pre>
}
<pre><code class="line-numbers">## 模板创建
settings->Editor->Code style->Live Templates
## 包
如果一个项目由多个人完成,但是这些人如果使用了同一个名字的类,就会产生冲突。这时需要用包来进行管理。
包的本质是文件夹
包的创建:src->右键->package->com.iweb
包的使用:在包的同级目录下创建Java class,编写这个java class的时候在开头import com.iweb.类名 就能调用包里面的类.同一个包内不需要import
包的命名 ![image-20220902221358313](E:/学习/Typora/笔记图片/image-20220902221358313.png)
![image-20220902221546184](E:/学习/Typora/笔记图片/image-20220902221546184.png)
![image-20220902222200679](E:/学习/Typora/笔记图片/image-20220902222200679.png)
## 继承
父函数的构造函数不会被继承
子类可以访问非私有的属性和方法,想要访问父类的私有属性,需要调用父类的公有或保护方法
super函数:当父类没有默认构造函数,只有有参构造函数时,子类调用(无参、有参)构造函数会报错,此时需要在子类的构造函数下使用super函数,指明父类的构造函数应该怎么构造
</code></pre>
//super必须放在子类构造器的第一行
<pre><code class="line-numbers"></code></pre>
//父类
public class base {
public base(String name){
System.out.println("base(String name)构造函数调用");
}
}
//子类
public class son extends base{
public son(String name){
super("name");//注意super不可少
System.out.println("son(String name)构造函数调用");
}
}
//main
public class main_test {
public static void main(String[] args) {
son s=new son("tom");
}
}
<pre><code class="line-numbers">“`base(String name)构造函数调用
//结果
base(String name)构造函数调用
son(String name)构造函数调用
java中所有类都是object的子类
父类构造器的调用不限于直接父类,将一直往上追溯到object类(顶级父类)
子类最多只能继承一个父类
访问修饰
super
super()只能在构造器中使用,而super.属性可以在子类函数中使用。但是super不能访问父类私有属性
如果子类有多个基类,且这些基类有重名的属性或者方法,则super的访问遵从就近原则。
覆盖
如果子类的某个方法和父类的方法名字、参数、返回值均一致,则子类的方法会覆盖父类的这个方法
子类方法的返回类型必须”小于等于“父类的返回类型,才能构成重写
子类方法不能缩小父类方法的访问权限
多态
编译阶段能调用哪些成员是由编译的类型决定的,如上面案例中,animal对象只能访问Animal类中的公有和保护成员,不能访问子类的任何成员。但是如果子类中如果存在重写父类成员的情况,animal会优先调用子类中重写的成员。
向下转型:当运行了
Animal animal=new Dog();
可以将animal转化成Dog类
animal=(Dog)animal;//转化成Dog后就可以访问Dog类的成员了
但是不可以把animal转化为cat
//animal=(Cat)animal是错误的
静态变量
静态变量是属于类本身的,同一类的所有对象都指向同一个静态变量
调用静态变量可以不用创建实例,直接用类名.静态变量就能调用
静态变量是在类加载的时候创建的,类加载是在第一次调用类的时候完成
静态方法
静态方法不能调用非静态变量,只能调用静态变量.如果一定要调用非静态变量,需要先创建本类的一个对象,在用这个对象调用非静态变量
普通方法也可以调用静态变量
代码块
创建子类对象实例的时候,父类也会被加载,而且父类会先被加载
代码块的执行优先级和类中静态变量的优先级是相同的,谁先出现先执行谁
package com.iweb;
public class main_test {
public static void main(String[] args) {
A a=new A();
}
}
class A{
{
System.out.println("普通代码块");
}
private int n=getn1();
public static int n2=getn2();
public A(){
System.out.println("A构造函数调用");
}
public int getn1(){
System.out.println("普通成员函数getn1调用");
return 100;
}
public static int getn2(){
System.out.println("静态成员函数getn2调用");
return 200;
}
}
运行结果:
静态成员函数getn2调用
普通代码块
普通成员函数getn1调用
A构造函数调用
package com.iweb;
public class main_test {
public static void main(String[] args) {
// A a=new A();
B b=new B();
}
}
class A{
{
System.out.println("普通代码块");
}
private int n=getn1();
public static int n2=getn2();
public A(){
System.out.println("A构造函数调用");
}
public int getn1(){
System.out.println("普通成员函数getn1调用");
return 100;
}
public static int getn2(){
System.out.println("静态成员函数getn2调用");
return 200;
}
}
class B extends A{
public static int n3=getn3();
public int n4=getn4();
public B(){
System.out.println("子类构造");
}
public static int getn3(){
System.out.println("子类静态getn4");
return 300;
}
public static int getn4(){
System.out.println("子类普通getn4");
return 400;
}
}
静态成员函数getn2调用
子类静态getn4
普通代码块
普通成员函数getn1调用
A构造函数调用
子类普通getn4
子类构造
单例模式饿汉式
package com.iweb;
public class main_test {
public static void main(String[] args) {
girlfriend gf=girlfriend.getinstance();
System.out.println(gf.getName());
}
}
//1.将构造器私有化
//2.类内部直接构造对象
//3.提供一个static方法,直接返回创建的对象
class girlfriend{
private String name;
private static girlfriend gf=new girlfriend("小红");
private girlfriend(String name){
this.name=name;
}
public static girlfriend getinstance(){
return gf;
}
public String getName() {
return name;
}
}
单例模式 懒汉式
public class cat {
public String name;
private static cat c;
public static int n=100;
private cat(String name){
this.name=name;
System.out.println("构造器调用");
}
public static cat getinstance(){
if(c==null){
cat c0=new cat("小猫");
return c0;
}
else return c;
}
public String getName() {
return name;
}
}
public class main_test {
public static void main(String[] args) {
System.out.println(cat.n);
System.out.println(cat.getinstance().getName());
}
}
100
构造器调用
小猫
//可以看到,在调用cat.n时不调用构造函数,未创建对象,只有在调用getinstance静态方法的时候,才创建了“小猫”对象
final
抽象类
抽象方法必须在抽象类中。
抽象类不能实例化。
抽象类可以没有抽象方法
抽象方法不能用private、final、static来修饰,因为这些关键字和重写是相违背的。
抽象模板
package com.iweb;
abstract public class template {
abstract public void job();
public void calulateTime(){
long start=System.currentTimeMillis();
job();
long end=System.currentTimeMillis();
System.out.println("执行时间"+(end-start));
}
}
package com.iweb;
public class AA extends template{
public void job(){
long n=0;
for(int i=0;i<1000000;i++){
n+=i;
}
}
}
package com.iweb;
public class BB extends template{
public void job(){
long n=1;
for(int i=1;i<200000;i++){
n*=i;
}
}
}
package com.iweb;
public class main_test {
public static void main(String[] args) {
AA aa=new AA();
aa.calulateTime();
BB bb=new BB();
bb.calulateTime();
}
}
接口
public interface interface01 {
public int n=10;//接口中的变量必须初始化
default public void hi(){//jdk8以后,接口中可以有默认方法
System.out.println("hi");
}
public static void ok(){//接口中可以有静态方法实现
System.out.println("ok");
}
public void chouxiang();//抽象方法,接入的类需要给所有的抽象方法写实现
}
接口不能被实例化。
接口中所有的方法是public,接口中方法可以不用abstract修饰
一个普通类实现接口,可以使用alt+enter以快速写出需要实现的方法有哪些(类刚写出名字时会爆红,此时光标需要放在爆红的上面)
抽象类可以不实现接口的方法
类只能继承一个父类,但是可以接入多个接口
接口中的变量int n=10;等价于public static final int n1=10;
package com.iweb;
public interface interface01 {
public int n=10;//接口中的变量必须初始化
default public void hi(){//jdk8以后,接口中可以有默认方法
System.out.println("hi");
}
public static void ok(){//接口中可以有静态方法实现
System.out.println("ok");
}
public void chouxiang();//抽象方法,接入的类需要给所有的抽象方法写实现
}
package com.iweb;
public class test implements interface01{
@Override
public void hi() {
interface01.super.hi();
}
@Override
public void chouxiang() {
}
}
package com.iweb;
public class main_test {
public static void main(String[] args) {
interface01 IF=new test();//这里IF是可以指向使用这个接口的类的
IF.hi();
}
}
instanceof 判断运行类型
内部类
package com.iweb;
public class outer {
private int n=100;
private void work02(){
System.out.println("hello,im work02");
}
public void work(){
class inner{//内部类定义在外部类的局部位置,一般定义在方法中
//内部类不能添加访问修饰符,只可以添加final,表示不能被继承
//内部类的作用域是在定义它的方法或者代码块中
//内部类可以直接访问外部类的成员,当内部类的变量和外部类的变量重名时,依据就近原则
//调用变量
//外部类在类方法中可以创建内部类的对象,然后调用对象的方法
int n=10;
public void f1(){
System.out.println("f1 work");
work02();
System.out.println("内部类n="+ n);
System.out.println("外部类n="+outer.this.n);
}
}
inner ie=new inner();
ie.f1();
}
}
package com.iweb;
public class main_test {
public static void main(String[] args) {
outer ou=new outer();
ou.work();
}
}
f1 work
hello,im work02
内部类n=10
外部类n=100
匿名内部类
package com.iweb;
public interface IA {
public void cry();
}
//使用匿名内部类的好处是不用写下面的代码
/*class tiger implements IA{
@Override
public void cry() {
System.out.println("老虎在叫唤");
}
}*/
package com.iweb;
public class outer {
public void method(){
IA tiger = new IA() {//按理说接口是不能创建实例的,但是如果在后面补上{方法体};就成为了匿名内部类
//这样做的好处是:如果只需要使用一次tiger类,再写tiger类接入接口IA很麻烦,不如使用匿名
//内部类,直接实现tiger的cry()方法
@Override
public void cry() {
System.out.println("老虎在叫唤");
}
};
tiger.cry();
}
}
package com.iweb;
public class main_test {
public static void main(String[] args) {
outer ou=new outer();
ou.method();
}
}
老虎在叫唤
成员内部类
写在外部类的成员位置上,可以被访问修饰符修饰
作用域在整个外部类,可以调用外部类的所有成员
静态内部类
成员内部类可以被static修饰,即为静态内部类。静态内部类只能访问外部类的静态变量
package com.iweb;
public class outer {
private static int n=100;
private int n1=200;
public static class AA{
public void sout(){
//System.out.println(n1),错误,不能访问非静态变量
System.out.println("n="+n);
}
}
public void method() {//外部类访问静态内部类
AA aa = new AA();
aa.sout();
}
}
class outer1{//外部其他类访问内部类
public outer1(){
outer.AA aa=new outer.AA();
aa.sout();
}
}
package com.iweb;
public class main_test {
public static void main(String[] args) {
outer1 ou=new outer1();
}
}
n=100
注解
与注释不同的是,注解会编译
@Override :表示下面的方法是父类的重写
装箱和拆箱
包装类转换
public static void main(String[] args) {
//Integer转Stirng
Integer i=100;
String s=i+"";
String s1=i.toString();
String s2=String.valueOf(i);
//String 转 Integer
String s3="1000";
Integer i1=Integer.parseInt(s3);
Integer i2=new Integer(s3);
}
对象对象判断的是这两个对象是不是同一个,而不是判断这两个对象是否有相同的成员.
Integer 100int 100 ->true
只要有基本数据类型,判断的都是值是否相等
//Integer源码
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
查看源码
ctrl+B查看某个方法的源码
ctrl+H查看某个类的源码
String
StringBuffer
串行化:对象可以在网络上传输也可以保存至文件中
StringBuilder
用于单线程,线程不安全
是StringBuffer的简易版
是final类,不可被继承
对象字符序列仍然是存放在其父类AbstractStringBuilder的char[] value中
Arrays
用于管理和操作数组
Integer[] integers={1,2,20,15,8};
System.out.println(Arrays.toString(integers));
Arrays.sort(integers);
System.out.println(Arrays.toString(integers));
[1, 2, 20, 15, 8]
[1, 2, 8, 15, 20]
动态绑定机制
java的动态绑定机制:当调用对象方法的时候,该方法会和该对象的运行类型绑定;当调用对象属性的时候,是哪个类的方法申请调用的,就使用哪个类的属性
package com.iweb;
public class father {
private int i=10;
public int sum1(){
return getI()+10;
}
public int sum2(){
return i+30;
}
public int getI(){
return i;
}
}
public class son extends father{
private int i=20;
public int sum1(){
return i+100;
}
public int sum2(){
return i+300;
}
public int getI(){
return i;
}
}
public class son1 extends father{//son1除了sum1方法被注释掉了,其他的成员完全和son一样
private int i=20;
// public int sum1(){
// return i+100;
// }
public int sum2(){
return i+300;
}
public int getI(){
return i;
}
}
package com.iweb;
import java.util.Arrays;
public class main_test {
public static void main(String[] args) {
father f=new son();
System.out.println(f.sum1());
System.out.println(f.sum2());
System.out.println("===========");
father f1=new son1();
System.out.println(f1.sum1());
System.out.println(f1.sum2());
}
}
120
320
===========
30
320
father f=new son()
左边的father是编译类型,右边是运行类型
调用对象方法的时候首先根据运行类型调用类方法,所以先调用了son的sum1(),结果是son的i+100
将son的sum1()注释掉之后(也就是son1),会先找son1的sum1方法,没有找到,然后从father中找,发现father中的sum1是要返回getI()+10。根据动态绑定机制,getI是类方法,是和运行类型绑定的,所以需要找son1的getI方法,得到的是son1的i=20,所以最终返回的是20+10=30
大数方法
Date
import java.util.Date
Date d1=new Date();//获取的是当前系统时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");//用SimpleDateFormat将日期转化成指定格式的字符串
String s=sdf.parse(s);
Date parse =sdf.parse(s);
泛型
package com.iweb;
public class Dog {
private String name;
private int age;
public Dog(String name,int age){
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Cat {
private String name;
private int age;
public Cat(String name,int age){
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.iweb;
import java.util.ArrayList;
import java.util.Arrays;
public class main_test {
public static void main(String[] args) {
// ArrayList arrayList = new ArrayList();
// arrayList.add(new Dog("大黄",5));
// arrayList.add(new Dog("小黄",1));
// arrayList.add(new Cat("招财猫",8));//不小心给数组中加入了一个CAt类型
// for(Object o:arrayList){
// o=(Dog)o;//遍历数组的时候必须使用Object类型接收。这里会报错,因为第三个误加入数组成员是Cat类的
// System.out.println(((Dog) o).getName()+"age"+((Dog) o).getAge());
// }
ArrayList<Dog> arrayList=new ArrayList<>();
arrayList.add(new Dog("大黄",5));
arrayList.add(new Dog("小黄",1));
arrayList.add(new Dog("旺财",8));
for(Dog dog:arrayList){//使用泛型就可以使用Dog来接收数组成员了
System.out.println(dog.getName()+":"+dog.getAge());
}
}
}
大黄:5
小黄:1
旺财:8
package com.iweb;
import java.util.ArrayList;
import java.util.Arrays;
public class main_test {
public static void main(String[] args) {
person<String> p=new person<>("人");
System.out.println(p.getName());
}
}
class person<E>{
private E name;
public person(E name) {
this.name = name;
}
public E getName() {
return name;
}
}
java画图
package com.iweb;
import javax.swing.*;
import javax.swing.plaf.multi.MultiPanelUI;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
@SuppressWarnings("all")
public class DrawCircle extends JFrame{//窗体
private MyPanel mp=null;//面板先默认置为空
public static void main(String[] args) {
new DrawCircle();
}
public DrawCircle(){
mp=new MyPanel();//默认调用paint
this.add(mp);//将面板加入到窗体中
this.setSize(400,300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//当窗体关闭的时候自动关闭程序
this.setVisible(true);
}
}
class MyPanel extends JPanel{
public void paint(Graphics g){
super.paint(g);
g.drawOval(10,10,100,100);
}
}
进程
代理模式
package Tread02;
public class Thread02 {
public static void main(String[] args) {
// Dog dog = new Dog();
// Thread thread=new Thread(dog);
// thread.start();
Tiger tiger = new Tiger();
Proxy proxy=new Proxy(tiger);
proxy.start();
}
}
class Proxy implements Runnable{//proxy是代理的意思
private Runnable target=null;
public Proxy(Runnable target) {
this.target = target;
}
public void start(){
start0();
}
public void start0(){
run();
}
@Override
public void run() {
if(target!=null){
target.run();
}
}
}
class Tiger implements Runnable{
@Override
public void run() {
System.out.println("老虎嗷嗷叫");
}
}
class Dog implements Runnable{
int count=0;
@Override
public void run() {
while (true){
System.out.println("小狗汪汪叫"+(++count)+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
if (count==10)break;
}
}
}
IP地址
IP地址:唯一标识主机
IPV6使用128位表示地址,IPV4用32位。所以IPV6采用16进制表示
web
网络。静态web程序不能进行数据库操作,动态web程序可以。web包括web服务器和web客户端。
B/S,V/S
B/S:浏览器/服务器(Browse/Server)结构,C/S:客户机/服务器(Client/Server)
JDBC
Driver driver=new driver();
String url="jdbc:mysql://localhost:3306/123";
Properties properties=new Properties();
properties.setProperty("user","root");
properties.setProperty("password","123");
Connection connect=driver.connect(url,properties);
String sql="***";//***应填充sql语句
Statement statement=connect.createStatement();
int rows=statement.excuteUpdate(sql);//受影响的行数
——————–
黑马java
UDP、TCP协议
UDP通信是不连接、不可靠通信,通常用于语音、视频。TCP是连接、可靠的通信,TCP通信的双方会采用三次握手建立可靠连接,保证数据能够可靠传输到服务端。
浅拷贝深拷贝
Object类中有保护方法clone()类继承了Cloneable接口就能够调用clone方法。创建新对象的时候不管是基本数据类型还是对象都是直接拷贝过来,(拷贝对象就是拷贝地址),这就是浅拷贝。这样如果一个对象的值被修改,所有浅拷贝得到的对象的值都会改变。
深克隆就是在继承了Cloneable的类中重写clone方法,对对象成员开辟新地址再赋值。
正则表达式
含义:校验字符串的规则
——————–
1-5
1.类方法
2.
Integer d1=new Integer(2017);
int d2=2017;
d1==d2的结果是?
3.接口中的方法默认是被什么修饰
4.不可变类
5.
6-10
6.Java EE、Java SE、Java ME
7、JDK、JRE
8.JSR、JCP
9.var关键字
10.cmd中java -version没有输出的问题(环境变量配置正确)
11-15
11.Java中整数的默认类型和浮点数的默认类型
12.java各部分代码执行顺序
13.线程的start和run方法
14.实现接口的方法可以是什么访问权限
15.一个Java源文件对类类型的定义有什么要求
16-20
16.继承时,对子类的限制
17.protected关键字
18.子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的
19.sealed类
20.向上转型
21-25
21.static能否修饰外部类
22.类的访问控制符
23.@override的作用
24.多态
25.Object类的方法
26-30
26.接口方法默认的访问控制类型
27.类名的完整形式
28.import
29.classpath
30.jar包和模块
31-35
31.字符串操作
32.Application、APPlet、Servelet
33.成员内部类,局部内部类,匿名内部类,静态内部类的访问修饰符分别可以是什么
34.静态变量能否在方法中定义
1-5
1.类方法
静态方法称为类方法,类方法没有this指针。静态方法在调用自己类中的方法时,可以不使用类名作用域的方式Class:: fun(),而直接调用。
2.
Integer d1=new Integer(2017);
int d2=2017;
d1==d2的结果是?
Integer和int比较会进行自动拆箱,比较的是数值大小,所以d1d2返回true
关于Integer和int的比较
①由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
Integer i = new Integer(100); Integer j = new Integer(100);
System.out.print(i == j); //false
②Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
Integer i = new Integer(100); int j = 100;
System.out.print(i == j); //true
③非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为 ①当变量值在-128~127之间时,非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同;②当变量值不在-128~127之间时,非new生成Integer变量时,java API中最终会按照new Integer(i)进行处理(参考下面第4条),最终两个Interger的地址同样是不相同的)
Integer i = new Integer(100); Integer j = 100;
System.out.print(i == j); //false
④对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100; Integer j = 100;
System.out.print(i == j); //true
Integer i = 128; Integer j = 128;
System.out.print(i == j); //false
对于第4条的原因:
java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而java API中对Integer类型的valueOf的定义如下:
public static Integer valueOf(int i){ assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high){ return IntegerCache.cache[i + (-IntegerCache.low)];
} return new Integer(i);
}
java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了
3.接口中的方法默认是被什么修饰
接口中方法默认被public abstract修饰,抽象方法不可以有方法体
JDK8中,接口中的方法可以被default和static修饰,但被修饰的方法必须有方法体
4.不可变类(Immutable Class)是一旦被实例化就不会改变自身状态(或值)的类。
String就是一种典型的不可变类。
不可变类的主要用途是在多线程环境下确保对象的线程安全。
不可变类一般建议使用final来修饰(比如String就是final类),否则子类可以通过继承不可变类的方式,增加setter方法,从而改变对象的状态,破坏了不可变的约束。
5.
\与equals是有明显区别的。强调栈中的比较,可以理解为地址比较 equals强调对象的内容比较 String s=“hello”;会在栈中生成hello字符串,并存入字符串常量池中。 String t=“hello” ;创建时,会在字符串常量池中寻找,当找到需要的hello时,不进行字符串的创建,引用已有的。 所以,s\t返回true,s.equals(t)也是true。 char c[]={‘h’,’e’,’l’,’l’,’o’}; c\s这个是不存在的,两边类型不同 t.equals(c)这个语句在anObject instanceof String这步判断不会通过,也就是cha[] 压根不能与String相比较,类型不是相同的。返回false
6-10
6.Java EE、Java SE、Java ME
Java SE就是标准版,包含标准的JVM和标准库,而Java EE是企业版,它只是在Java SE的基础上加上了大量的API和库,以便方便开发Web应用、数据库、消息服务等,Java EE的应用使用的虚拟机和Java SE完全相同。
Java ME就和Java SE不同,它是一个针对嵌入式设备的“瘦身版”,Java SE的标准库无法在Java ME上使用,Java ME的虚拟机也是“瘦身版”。
毫无疑问,Java SE是整个Java平台的核心,而Java EE是进一步学习Web应用所必须的。我们熟悉的Spring等框架都是Java EE开源生态系统的一部分。不幸的是,Java ME从来没有真正流行起来,反而是Android开发成为了移动平台的标准之一,因此,没有特殊需求,不建议学习Java ME。
7.JDK、JRE
8.JSR、JCP
- JSR规范:Java Specification Request
- JCP组织:Java Community Process
为了保证Java语言的规范性,SUN公司搞了一个JSR规范,凡是想给Java平台加一个功能,比如说访问数据库的功能,大家要先创建一个JSR规范,定义好接口,这样,各个数据库厂商都按照规范写出Java驱动程序,开发者就不用担心自己写的数据库代码在MySQL上能跑,却不能跑在PostgreSQL上。
所以JSR是一系列的规范,从JVM的内存模型到Web程序接口,全部都标准化了。而负责审核JSR的组织就是JCP。
9.var关键字
var sb = new StringBuilder();
编译器会根据赋值语句自动推断出变量sb的类型是StringBuilder,上面的语句会自动变成下面的:
StringBuilder sb = new StringBuilder();
10.cmd中java -version没有输出的问题(环境变量配置正确)
11-15
11.Java中整数的默认类型和浮点数的默认类型
整数类型int、浮点类型double
12.java各代码部分执行顺序
父类静态代码块、静态变量 ps:按声明顺序执行
子类静态代码块、静态变量 ps:按声明顺序执行
父类局部代码块、成员变量 ps:按声明顺序执行
父类构造函数
子类局部代码块、成员变量 ps:按声明顺序执行
子类构造函数
13.
Thread的start和run方法 用start方法才能真正启动线程,此时线程会处于就绪状态,一旦得到时间片,则会调用线程的run方法进入运行状态。 而run方法只是普通方法,如果直接调用run方法,程序只会按照顺序执行主线程这一个线程
14.
①必须实现接口中所有的方法。
在实现类中实现接口时,方法的名字、返回值类型、参数的个数及类型必须与接口中的完全一致,并且必须实现接口中的所有方法。
②接口实现类相当于子类,子类的访问权限是不能比父类小的。
接口中所有方法默认都是public,至于为什么要是public,原因在于如果不是public,那么只能在同个包下被实现,可访问权限就降低很多了,那么在实现类中,实现的类相当于子类,子类的访问权限是不能比父类小的,而在java中一个类如果没有权限的修饰符,默认是friendly(同一个包内的其它类才可访问),所以在实现类中一定要写public
15.一个Java源文件可以包含多个类的定义,但只能定义一个public类,且public类名必须与文件名一致。如果要定义多个public类,必须拆到多个Java源文件中
16-20
16.继承时,对子类的限制
严禁定义与父类重名的字段!
任何class
的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();
17.protected关键字
protected
关键字可以把字段和方法的访问权限控制在继承树内部
18.子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的
19.sealed类
20.向上转型
21-25
21.static能否修饰外部类
static修饰的为类成员,会随着类的加载而加载,比如静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等,可以想象一下,如果把一个Class文件中的外部类设为static,目的难道是让这个类随着应用的启动而加载吗?如果在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。
而为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果没有使用静态来修饰,那么在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。
最终结论就是:static可以用来修饰内部类,但是不可以用来修饰外部类
22.类的访问控制符
23.@override会让编译器检查子类对父类函数的覆写,但是@override不是必须的
24.多态
多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法
// Polymorphic
public class Main {
public static void main(String[] args) {
// 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
Income[] incomes = new Income[] {
new Income(3000),
new Salary(7500),
new StateCouncilSpecialAllowance(15000)
};
System.out.println(totalTax(incomes));
}
public static double totalTax(Income... incomes) {
double total = 0;
for (Income income: incomes) {
total = total + income.getTax();
}
return total;
}
}
class Income {
protected double income;
public Income(double income) {
this.income = income;
}
public double getTax() {
return income * 0.1; // 税率10%
}
}
class Salary extends Income {
public Salary(double income) {
super(income);
}
@Override
public double getTax() {
if (income <= 5000) {
return 0;
}
return (income - 5000) * 0.2;
}
}
class StateCouncilSpecialAllowance extends Income {
public StateCouncilSpecialAllowance(double income) {
super(income);
}
@Override
public double getTax() {
return 0;
}
}
/*观察totalTax()方法:利用多态,totalTax()方法只需要和Income打交道,它完全不需要知道Salary和StateCouncilSpecialAllowance的存在,就可以正确计算出总的税。如果我们要新增一种稿费收入,只需要从Income派生,然后正确覆写getTax()方法就可以。把新的类型传入totalTax(),不需要修改任何代码。
可见,多态具有一个非常强大的功能,就是允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。*/
25.Object类的方法
toString()
:把instance输出为String
;equals()
:判断两个instance是否逻辑相等;hashCode()
:计算一个instance的哈希值。
26-30
26.接口方法默认的访问控制类型
public abstract
27.类名的完整形式
包名.类名,在Java虚拟机执行的时候,JVM只看完整类名,因此,只要包名不同,类就不同。
包没有父子关系。java.util和java.util.zip是不同的包,两者没有任何继承关系。
28.import
在一个class
中,我们总会引用其他的class
。例如,小明的ming.Person
类,如果要引用小军的mr.jun.Arrays
类,他有三种写法:
第一种,直接写出完整类名,例如:
// Person.java
package ming;
public class Person {
public void run() {
// 写完整类名: mr.jun.Arrays
mr.jun.Arrays arrays = new mr.jun.Arrays();
}
}
很显然,每次写完整类名比较痛苦。
因此,第二种写法是用import
语句,导入小军的Arrays
,然后写简单类名:
// Person.java
package ming;
// 导入完整类名:
import mr.jun.Arrays;
public class Person {
public void run() {
// 写简单类名: Arrays
Arrays arrays = new Arrays();
}
}
在写import
的时候,可以使用*
,表示把这个包下面的所有class
都导入进来(但不包括子包的class
):
// Person.java
package ming;
// 导入mr.jun包的所有class:
import mr.jun.*;
public class Person {
public void run() {
Arrays arrays = new Arrays();
}
}
我们一般不推荐这种写法,因为在导入了多个包后,很难看出Arrays
类属于哪个包。
还有一种import static
的语法,它可以导入一个类的静态字段和静态方法:
package main;
// 导入System类的所有静态字段和静态方法:
import static java.lang.System.*;
public class Main {
public static void main(String[] args) {
// 相当于调用System.out.println(…)
out.println("Hello, world!");
}
}
import static
很少使用。
Java编译器最终编译出的.class
文件只使用完整类名,因此,在代码中,当编译器遇到一个class
名称时:
- 如果是完整类名,就直接根据完整类名查找这个
class
; - 如果是简单类名,按下面的顺序依次查找:
- 查找当前
package
是否存在这个class
; - 查找
import
的包是否包含这个class
; - 查找
java.lang
包是否包含这个class
。
- 查找当前
如果按照上面的规则还无法确定类名,则编译报错。
注意:
①自动导入的是java.lang包,但类似java.lang.reflect这些包仍需要手动导入
②如果有两个class
名称相同,例如,mr.jun.Arrays
和java.util.Arrays
,那么只能import
其中一个,另一个必须写完整类名。
29.classpath
classpath
是JVM用到的一个环境变量,它用来指示JVM如何搜索class
。
因为Java是编译型语言,源码文件是.java
,而编译后的.class
文件才是真正可以被JVM执行的字节码。因此,JVM需要知道,如果要加载一个abc.xyz.Hello
的类,应该去哪搜索对应的Hello.class
文件。
所以,classpath
就是一组目录的集合,它设置的搜索路径与操作系统相关。例如,在Windows系统上,用;
分隔,带空格的目录用""
括起来,可能长这样:
30.jar包和模块
如果有很多.class
文件,散落在各层目录中,肯定不便于管理。如果能把目录打一个包,变成一个文件,就方便多了。
jar包就是用来干这个事的,它可以把package
组织的目录层级,以及各个目录下的所有文件(包括.class
文件和其他文件)都打成一个jar文件,这样一来,无论是备份,还是发给客户,就简单多了。
jar包实际上就是一个zip格式的压缩文件,而jar包相当于目录。如果我们要执行一个jar包的class
,就可以把jar包放到classpath
中:
java -cp ./hello.jar abc.xyz.Hello
这样JVM会自动在hello.jar
文件里去搜索某个类。
那么问题来了:如何创建jar包?
因为jar包就是zip包,所以,直接在资源管理器中,找到正确的目录,点击右键,在弹出的快捷菜单中选择“发送到”,“压缩(zipped)文件夹”,就制作了一个zip文件。然后,把后缀从.zip
改为.jar
,一个jar包就创建成功。
jar只是用于存放class的容器,它并不关心class之间的依赖,所以需要引入模块。引入的模块,主要是为了解决“依赖”这个问题。如果a.jar
必须依赖另一个b.jar
才能运行,那我们应该给a.jar
加点说明啥的,让程序在编译和运行的时候能自动定位到b.jar
,这种自带“依赖关系”的class容器就是模块。
31-35
31.字符串操作
s1.equals(s2)//字符串内容比较.==是比较引用
s1.equalsIgnoreCase(s2)//字符串忽略大小写比较
s1.contains(s2);在s1中搜索子串s2
s1.substring(i,j);//提取s1在[i,j)的子串,ij都是以0为下标的
s.trim();//移除首尾空白字符\r\n\t
......
- 1.Application:Java应用程序,是可以由Java解释器直接运行的程序。 2.Applet:即Java小应用程序,是可随网页下载到客户端由浏览器解释执行的Java程序。
3.Servlet:Java服务器端小程序,由Web服务器(容器)中配置运行的Java程序。…
33.
在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类,广泛意义上的内部类一般包括四种:成员内部类,局部内部类,匿名内部类,静态内部类 。
1.成员内部类
(1)该类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员);
(2)成员内部类拥有与外部类同名的成员变量时,会发生隐藏现象,即默认情况下访问的是成员内部类中的成员。如果要访问外部类中的成员,需要以下形式访问:【外部类.this.成员变量 或 外部类.this.成员方法】;
(3)在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问;
(4)成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象;
(5)内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类用private修饰,则只能在外部类的内部访问;如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。外部类只能被public和包访问两种权限修饰。
2.局部内部类
(1)局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;
(2)局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
3.匿名内部类
(1)一般使用匿名内部类的方法来编写事件监听代码;
(2)匿名内部类是不能有访问修饰符和static修饰符的;
(3)匿名内部类是唯一一种没有构造器的类;
(4)匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
4.内部静态类
(1)静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似;
(2)不能使用外部类的非static成员变量或者方法。
34.Java中静态变量只能在类主体中定义,不能在方法中定义。 静态变量属于类所有而不属于方法