1 - &
与 &&
的区别:
&
:不管左边是true
还是false
,右端都会进行运算;&&
:当左端为false
时,右端不再进行运算;- 即在
与
运算时,前面为false
,即可判断该条件为false
了,后面没必要再算了 ----建议使用&&
.
2 - |
与 ||
的区别:
|
:不管左端,右端照算;||
:左端为true
时,右端不用算(最终结果已经可以确定为true
了);- 建议用
||
3 - java中内存的基本结构:
4 - this
关键字的使用:
- 1 - 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加
this
来表明该变量的类成员;- 2 - 在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加
this
,增强程序的阅读性;- 3 - this可以作为一个类中,构造器相互条用的特殊格式;
public Person(String name){
this(); //调用本类中的无参构造方法
this.name = name;
}
public Person(String name, int age){
this(name); //调用有一个参数的构造方法
this.age = age;
}
5 - this
和super
的区别:
No. | 区别点 | this | super |
---|---|---|---|
1 | 访问属性 | 访问本类中的属性,如果本类中没有此属性,则从父类中继续查找 | 访问父类中的属性 |
2 | 调用方法 | 访问本类中的方法 | 直接访问父类中的方法 |
2 | 调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
4 | 特殊 | 表示当前对象 | 无此概念 |
6 - 权限修饰符的区别:
- private :无法被子类继承,也无法被外部类调用;
- protected :显示的表示可以被子类继承;
- public : 可以被外部类直接调用;
7 - java
中的多态:
Person
父类,有eat()
,walk()
;Man
和 Woman
为继承了 Person
类的子类,并且都重写了eat()
和walk()
方法,
另外,Woman
类中有一个自己的方法,即shooping()
Man m = new Man();
m.eat();
m.walk();
System.out.println(); //*【子类对象的多态性】:父类的引用指向子类对象
Person p1 = new Man(); //向上转型
//虚拟方法调用:通过父类的引用指向子类对象的实体,当调用方法时,执行的是子类重写父类的方法
p1.eat();
p1.walk(); Person p2 = new Woman();
p2.eat();
p2.walk();
Woman w = (Woman)p2; //向下转型
w.shooping();
补充:instanceof
:类型判断
//格式:对象p instanceof 类A
if(p1 instanceof Woman){
//如果p1是Woman类型,则可以转型
Woman w1 = (Woman)p1;
w1.shooping();
}
8 - static
修饰属性(类变量):
1.由类创建的所有对象,都共用这一个属性
2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static
变量修饰的属性
3.类变量随着类的加载而加载的,而且独一份
4.静态的变量可以直接通过“类.类变量”的形式来调用
5.类变量的加载要早于对象。所以当有对象以后,可以“类.类变量”使用。但是“类.实例变量”是不行的。
6.类变量存在与静态域中。
class SportMan{
//实例变量(随着对象的创建而被加载的)
String name;
int age;
//类变量
static String nation; }
8 - static
修饰方法(类方法):
1.随着类的加载而加载,在内存中也是独一份
2.可以直接通过“类.类方法”的方式调用
3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法可以调用静态的属性或静态的方法
>静态的方法内是不可以有this或super关键字的!
注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,被回收也要晚于非静态的结构
>可以简单记住:加了static
的方法和变量,可以不new
一个对象而直接通过类.方法名
或类.变量名
来调用,例如:
class Black{
Test.bianliang; //直接调用,而不需要new一个
Test.fangfa(); //直接调用,而不需要new一个
}
Class Test{ public static int bianliang = 666; public static void fangfa(){
System.out.println("测试方法");
}
}
9 - 单例模式
【推荐阅读博客】:https://blog.csdn.net/goodlixueyong/article/details/51935526
1.解决的问题:使得一个类只能创建一个对象。
2.如何实现?见如下4步
//饿汉式
public class TestSingleton{
public static void main(String[] args){
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getINstance();
System.out.println(s1 == s2); //比较两个对象的引用是否一样
//而equal()用来比较两个对象是否一样
}
} //只能创建Singleton的单个实例
class Singleton{
//1.私有化构造器,使得在类的外部不能够调用次构造器
private Singleton(){ } //2.在类的内部创建一个类的实例
private static Singleton instance = new Singleton(); //3.私有化此对象,通过公共的方法来调用
//4.此公共的方法,只能通过类来调用,因为设置为static的,同时类的实例也必须为static声明的
public static Singleton getInstance(){
return instance;
}
}
ture
//懒汉式:可能存在线程安全问题
public class TestSingleton1{
public static void main(String[] args){
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getINstance();
System.out.println(s1 == s2);
}
} class Singleton1{
//1.私有化构造器
private Singleton1(){ } //2.在类的内部创建一个类的实例,并使其为私有和静态的
private static Sintleton1 instance = null; //3.返回对象
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
10 - final修饰
- 1.final修饰类:这个类就不能被继承;
- 2.final修饰方法:这个方法不能被子类重写;
- 3.final修饰属性:此属性就是一个常量,一旦初始化,就不能再赋值。习惯上常量有大写字母表示;
11 - java集合
Collection
接口:
Set
:元素无序、不可重复的集合;List
:元素有序,可重复的集合;
Map接口:具有映射关系“key-value”的集合;
12 - java
中的接口
- 1.接口可以看作是一个特殊的抽象类。是常量与抽象方法的一个集合,不能包含变量、一般的方法。
- 2.接口是没有构造器的;
- 3.接口定义的就是一种功能。 此功能可以被类所实现(
implements
);比如:class CC extends DD implements AA
- 4.实现接口的类,必须要重写其中的所有的抽象方法,方可实例化。若没有重写,则仍为抽象类;
- 5.类可以实现多个接口。 -----
java
中类的的继承是单继承的;- 6.接口与接口之间也是继承的关系,而且可以实现多继承。
- <5、6是面试的重点>
13 - 集合的使用
Collection
接口:
List
接口:存储有序的,可以重复的元素 ---- 相当于“动态”数组;
》添加进List集合中的元素(或对象)所在的类一定要重写equals()
方法;
ArrayList
(主要的实现类)LinkedList
(链表形式的实现类,更适用于频繁的插入、删除操作)Vector
(古老的实现类、线程安全的,但效率要低于ArrayList
)
Set
接口:存储无序的,不可重复的元素 ---- 相当于高中的集合概念
》添加进Set集合中的元素所在的类一定要重写equals()
和hashCode()
方法;
HashSet
(主要的实现类)LinkedHashSet
(是HashSet
的子类,当我们遍历集合元素时,是按照添加进去的顺序实现的)TreeSet
(可以按照添加进集合中的元素的制定属性进行排序)
- 要求
TreeSet
添加进的元素必须是同一个类的!- 两种排序方式:
- 自然排序:
- ①要求添加进
TreeSet
中的元素所在类implementS Comparable
接口- ②重写
compareTo(Object obj)
,在此方法内指明按照元素的哪个属性进行排序- ③向
TreeSet
中添加元素即可,若不实现此接口,会报运行时异常
- 定制排序:
- ①创建一个实现
Comparator
接口的实现类的对象,在实现类中重写Comparator
的方法- ②在此
compare()
方法中指明按照元素所在类的哪个属性进行排序- ③将此实现
Comparator
接口的实现类的对象作为形参传递给TreeSet
的构造器中- ④向
TreeSet
中添加元素即可,若不实现次接口,会报运行时异常
- 》要求重写的
compareTo()
或者compare()
方法与equals()和hashCode()
方法保持一致。
Map
接口:存储“键-值”对的数据 ---- 相当与高中的“函数 y = f(x)”
- key是不可重复的,使用Set存放。value可以重复,使用Collection来存放的。一个key-value构成一个entry(Map.Entry),entry使用Set来存放
- HashMap:主要的实现类,可以添加null键,null值
- LinkedHashMap:是HashMap的子类,可以按照添加进Map的顺序实现遍历
- TreeMap:需要按照key所在类的制定属性进行排序,要求key是同一个类的对象,对key考虑使用自然排序 或 定制排序
- HashTable:是一个古老的实现类,线程安全的,不可以添加进null键,null值;不建议使用。
- 子类:Properties:重用来处理属性文件(如数据库的配置文件)
14 - java
多线程
//使用实现Runnable接口的方式,售票
/**
* 此线程会存在线程安全问题
* 2.如何来解决线程的安全问题?
* 必须让一个线程操作共享数据完毕后,其他线程才有机会参与共享数据的操作
*
* 3.java如何实现线程的安全:线程的同步机制
*
* 方式一:同步代码块
* synchronized(同步监视器){
* //需要被同步的代码(即为操作共享数据的代码)
* }
* 1.共享数据:多个线程共同操作的同一个数据(变量)
* 2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁
* 要求:所有的线程必须共用同一把锁!
* 注:在实现的方式中,考虑同步的话,可以使用this来充当锁。但是在继承的方法中,慎用this
*
* 方式二:同步方法
* 将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行此方法时,
* 其他线程在外等待直至此线程执行完此方法。
*
* @author hasee
*
*/ //实现的方式
//加锁实现同步(同步代码块)
class Window1 implements Runnable {
int ticket = 100; Object obj = new Object(); public void run() {
while (true) {
synchronized (obj) {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
} //实现的方式(通过静态共享变量保证多个线程修改的是同一个变量)
class Window2 implements Runnable {
static int ticket = 100; public void run() {
while (true) {
if (ticket > 0) {
try {
Thread.currentThread().sleep(10); //将多线程的错误放大
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
} //同步的方式(通过继承的方式来实现多线程)
class Window3 extends Thread {
static int ticket = 100;
static Object obj = new Object(); //静态的监视器,避免不同进程使用不同的监视器,造成无法同步的安全问题
public void run(){
while(true){
synchronized (obj) {
if(ticket > 0){
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
} }
}
} //同步的方法(通过接口实现)
class Window4 implements Runnable {
int ticket = 100; //共享数据 public void run() {
while (true) {
show();
}
} //将该方法声明为synchronized方法
public synchronized void show(){
if (ticket > 0) {
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
} public class TestWindow1 {
public static void main(String[] args) {
// 方式一:3个Thread共享一个Window1类对象
Window1 w = new Window1();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.start();
t2.start();
t3.start(); // 方式二:三个Window2类对象,各自分别对应了3个Thread
// 这种方式必须保证共享的变量(即共享资源)为静态的,否则出错
// Window2 w21 = new Window2();
// Window2 w22 = new Window2();
// Window2 w23 = new Window2();
// Thread t21 = new Thread(w21);
// Thread t22 = new Thread(w22);
// Thread t23 = new Thread(w23);
// t21.start();
// t22.start();
// t23.start(); }
}