Java编程面试问题的前50名

介绍

如果你正在面试Java编程角色,那么你的编码能力可能会受到考验。无论你是Java初学者还是专家程序员,本文提供了一些常见的Java面试问题和答案,以帮助你做好准备。

在Java中如何反转字符串?

在String类中没有reverse()工具方法。然而,您可以从字符串创建一个字符数组,然后从末尾到开头迭代它。您可以将字符添加到一个字符串构建器中,最后返回反转后的字符串。

以下的示例代码展示了一种反转字符串的方法:

public class StringPrograms {

	public static void main(String[] args) {
		String str = "123";

		System.out.println(reverse(str));
	}

	public static String reverse(String in) {
		if (in == null)
			throw new IllegalArgumentException("Null is not valid input");

		StringBuilder out = new StringBuilder();

		char[] chars = in.toCharArray();

		for (int i = chars.length - 1; i >= 0; i--)
			out.append(chars[i]);

		return out.toString();
	}

}

在方法中添加空值检查并使用StringBuilder来追加字符,将会获得奖励分。请注意,在Java中索引从0开始,所以在for循环中应从chars.length – 1 开始。

在Java中,不使用第三个变量,你如何交换两个数字?

不使用第三个变量进行交换数字是一个三步骤的过程,在代码中更容易进行可视化。

b = b + a; // now b is sum of both the numbers
a = b - a; // b - a = (b + a) - a = b (a is swapped)
b = b - a; // (b + a) - b = a (b is swapped)

以下示例代码展示了一种实现数字交换方法的方式:

public class SwapNumbers {

public static void main(String[] args) {
	int a = 10;
	int b = 20;

    System.out.println("a is " + a + " and b is " + b);

	a = a + b;
	b = a - b;
	a = a - b;

    System.out.println("After swapping, a is " + a + " and b is " + b);
    }

}

输出显示整数值已交换。


Output

a is 10 and b is 20 After swapping, a is 20 and b is 10

写一个Java程序来检查一个字符串中是否存在元音字母。

下面的示例代码展示了如何使用正则表达式来检查字符串是否包含元音字母。

public class StringContainsVowels {

	public static void main(String[] args) {
		System.out.println(stringContainsVowels("Hello")); // true
		System.out.println(stringContainsVowels("TV")); // false
	}

	public static boolean stringContainsVowels(String input) {
		return input.toLowerCase().matches(".*[aeiou].*");
	}

}

写一个Java程序来检查给定的数字是否是质数。

你可以编写一个程序,将给定的数字n除以2到n/2之间的数字,并检查余数。如果余数为0,则它不是一个质数。以下示例代码展示了一种检查给定数字是否为质数的方法:

public class PrimeNumberCheck {

	public static void main(String[] args) {
		System.out.println(isPrime(19)); // true
		System.out.println(isPrime(49)); // false
	}

	public static boolean isPrime(int n) {
		if (n == 0 || n == 1) {
			return false;
		}
		if (n == 2) {
			return true;
		}
		for (int i = 2; i <= n / 2; i++) {
			if (n % i == 0) {
				return false;
			}
		}

		return true;
	}

}

尽管这个程序能够正常工作,但它在内存和时间效率上表现不佳。请考虑以下情况:对于给定数N,如果在2到√N(N的平方根)之间存在一个能够整除N的质数M,那么N就不是一个质数。

写一个使用递归的Java程序,打印出一个斐波那契序列。

斐波那契数列是一种每个数字都是前两个数字之和的数列。在这个例子中,数列从0和1开始。下面的示例代码展示了如何使用for循环打印斐波那契数列。

public class PrintFibonacci {

	public static void printFibonacciSequence(int count) {
		int a = 0;
		int b = 1;
		int c = 1;

		for (int i = 1; i <= count; i++) {
			System.out.print(a + ", ");

            a = b;
			b = c;
			c = a + b;
		}
	}

	public static void main(String[] args) {
    	printFibonacciSequence(10);
	}

}

Output

0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

你也可以使用递归来打印斐波那契数列,因为斐波那契数是通过在序列中加上前两个数字生成的。

F(N) = F(N-1) + F(N-2)

下面的示例类展示了如何使用递归来计算长度为10的斐波那契数列。

public class PrintFibonacciRecursive {

    public static int fibonacci(int count) {
		if (count <= 1)
			return count;

		return fibonacci(count - 1) + fibonacci(count - 2);
	}

	public static void main(String args[]) {
    	int seqLength = 10;

    	System.out.print("A Fibonacci sequence of " + seqLength + " numbers: ");

    	for (int i = 0; i < seqLength; i++) {
      	    System.out.print(fibonacci(i) + " ");
    	}
  	}

}

Output

A Fibonacci sequence of 10 numbers: 0 1 1 2 3 5 8 13 21 34

在Java中,你如何检查一个整数列表是否只包含奇数?

你可以使用一个for循环,并检查每个元素是否为奇数。

public static boolean onlyOddNumbers(List<Integer> list) {
	for (int i : list) {
		if (i % 2 == 0)
			return false;
	}

	return true;
}

如果列表很大,您可以使用并行流进行更快的处理,如下面的示例代码所示:

public static boolean onlyOddNumbers(List<Integer> list) {
	return list
			.parallelStream() // parallel stream for faster processing
			.anyMatch(x -> x % 2 != 0); // return as soon as any elements match the condition
}

若要了解判断整数是否为奇数的数学背后,请参考维基百科上的模运算。

7. 在Java中,你如何检查一个字符串是否是回文?

回文串是指正序和倒序都相同的字符串。要检查一个字符串是否为回文串,可以将输入字符串反转并检查结果是否与输入相等。下面的示例代码展示了如何使用String charAt(int index)方法来检查回文串:

boolean checkPalindromeString(String input) {
	boolean result = true;
	int length = input.length();

	for (int i = 0; i < length/2; i++) {
		if (input.charAt(i) != input.charAt(length - i - 1)) {
			result = false;
			break;
		}
	}

	return result;
}

8. 在Java中,如何去除字符串中的空格?

下面的示例代码展示了使用Character.isWhitespace()方法从字符串中删除空格的一种方法。

String removeWhiteSpaces(String input) {
	StringBuilder output = new StringBuilder();
	
	char[] charArray = input.toCharArray();
	
	for (char c : charArray) {
		if (!Character.isWhitespace(c))
			output.append(c);
	}
	
	return output.toString();
}

了解如何在Java中删除字符串中的空格和其他字符。

9. 在Java中,你如何去除字符串的前导和尾随空格?

String类包含两个方法来删除前导和尾随的空格:trim()和strip()。strip()方法是在Java 11中添加到String类中的。strip()方法使用Character.isWhitespace()方法来检查字符是否为空格。这个方法使用Unicode代码点,而trim()方法将任何代码点值小于或等于U+0020的字符标识为空格字符。

strip()方法是推荐的去除空白字符的方式,因为它使用了Unicode标准。下面的示例代码展示了如何使用strip()方法去除空白字符。

String s = "  abc  def\t";
		
s = s.strip();
		
System.out.println(s);

由于字符串是不可变的,所以您必须将strip()的输出赋给该字符串。

10. 在Java中如何对数组进行排序?

Arrays工具类有许多重载的sort()方法,可以用于排序原始数组和对象数组。如果要按照自然顺序对原始数组进行排序,可以使用Arrays.sort()方法,如下例所示:

int[] array = {1, 2, 3, -1, -2, 4};

Arrays.sort(array);

System.out.println(Arrays.toString(array));

然而,如果你想要对一个对象数组进行排序,那么这个对象必须实现Comparable接口。如果你想要指定排序的标准,你可以传入Comparator来定义排序逻辑。在Java中了解更多关于Comparable和Comparator的知识。

11. 如何在Java中以编程方式创建死锁场景?

死锁是在多线程Java环境中的一种情况,其中两个或更多线程被永久阻塞。死锁的情况发生在至少两个线程之间。以下示例代码创建了一个死锁情景。

public class ThreadDeadlock {

    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
    
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
        
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();        
    }

}

class SyncThread implements Runnable {

    private Object obj1;
    private Object obj2;

    public SyncThread(Object o1, Object o2) {
        this.obj1 = o1;
        this.obj2 = o2;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();

        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
            System.out.println(name + " acquiring lock on " + obj2);
            synchronized (obj2) {
                System.out.println(name + " acquired lock on " + obj2);
                work();
            }
            System.out.println(name + " released lock on " + obj2);
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " finished execution.");
    }

    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

所有三个线程都能够锁定第一个对象。但是,它们正在使用共享资源,并且以一种无限等待来启动,以获取第二个对象的锁定。您可以使用Java线程转储来检测死锁。了解更多有关Java中死锁的信息。

如何在Java中找到整数的阶乘?

一个整数的阶乘是通过将从1到给定数字的所有数字相乘来计算的。

F(n) = F(1)*F(2)...F(n-1)*F(n)

下面的示例代码展示了如何使用递归来计算一个整数的阶乘。

public static long factorial(long n) {
	if (n == 1)
		return 1;
	else
		return (n * factorial(n - 1));
}

13. 如何在Java中反转一个链表?

LinkedList的descendingIterator()方法返回一个以相反顺序遍历元素的迭代器。以下示例代码展示了如何使用此迭代器以相反顺序创建一个新的链表,其中元素按相反顺序列出。

LinkedList<Integer> ll = new LinkedList<>();

ll.add(1);
ll.add(2);
ll.add(3);

System.out.println(ll);

LinkedList<Integer> ll1 = new LinkedList<>();

ll.descendingIterator().forEachRemaining(ll1::add);

System.out.println(ll1);

从数据结构和算法的角度更多地了解如何逆转链表。

14. 在Java中如何实现二分查找?

为了实现二分查找,数组元素必须被排序。二分查找算法基于以下条件:

  • If the key is less than the middle element, then you now need to search only in the first half of the array.
  • If the key is greater than the middle element, then you need to search only in the second half of the array.
  • If the key is equal to the middle element in the array, then the search ends.
  • Finally, if the key is not found in the whole array, then it should return -1. This indicates that the element is not present.

以下是一个实现二分查找的示例代码。

public static int binarySearch(int arr[], int low, int high, int key) {
	int mid = (low + high) / 2;

	while (low <= high) {
		if (arr[mid] < key) {
			low = mid + 1;
		} else if (arr[mid] == key) {
			return mid;
		} else {
			high = mid - 1;
		}
		mid = (low + high) / 2;
	}

	if (low > high) {
		return -1;
	}

	return -1;
}

请编写一个Java程序来演示归并排序。

归并排序是其中一个效率最高的排序算法之一。它基于“分而治之”的原则进行操作。它的思想是将列表逐渐分解为多个子列表,直到每个子列表只包含一个元素,然后以一种使结果为排序列表的方式合并这些子列表。下面的示例代码展示了使用归并排序的一种方式。

public class MergeSort {

	public static void main(String[] args) {
		int[] arr = { 70, 50, 30, 10, 20, 40, 60 };

		int[] merged = mergeSort(arr, 0, arr.length - 1);

		for (int val : merged) {
			System.out.print(val + " ");
		}
	}

	public static int[] mergeTwoSortedArrays(int[] one, int[] two) {
		int[] sorted = new int[one.length + two.length];

		int i = 0;
		int j = 0;
		int k = 0;

		while (i < one.length && j < two.length) {
			if (one[i] < two[j]) {
				sorted[k] = one[i];
				k++;
				i++;
			} else {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (i == one.length) {
			while (j < two.length) {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (j == two.length) {
			while (i < one.length) {
				sorted[k] = one[i];
				k++;
				i++;
			}
		}

		return sorted;
	}

	public static int[] mergeSort(int[] arr, int lo, int hi) {
		if (lo == hi) {
			int[] br = new int[1];
			br[0] = arr[lo];

			return br;
		}

		int mid = (lo + hi) / 2;

		int[] fh = mergeSort(arr, lo, mid);
		int[] sh = mergeSort(arr, mid + 1, hi);

		int[] merged = mergeTwoSortedArrays(fh, sh);

		return merged;
	}

}

你能用Java创建一个字符金字塔吗?

模式程序是一个非常流行的面试题目。这种类型的问题用于了解面试者的逻辑思维能力。请参考Java中的金字塔模式程序示例,了解创建金字塔模式的不同方法。

17. 编写Java程序,检查两个数组是否包含相同的元素。

为了检查两个数组是否包含相同的元素,你需要首先从这两个数组中创建一个元素集合,然后比较这些集合中的元素,以确定是否存在一个在两个集合中都不存在的元素。以下示例代码展示了如何检查两个数组是否只包含相同的元素:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArraySameElements {

	public static void main(String[] args) {
		Integer[] a1 = {1,2,3,2,1};
		Integer[] a2 = {1,2,3};
		Integer[] a3 = {1,2,3,4};
		
		System.out.println(sameElements(a1, a2));
		System.out.println(sameElements(a1, a3));
	}

	static boolean sameElements(Object[] array1, Object[] array2) {
		Set<Object> uniqueElements1 = new HashSet<>(Arrays.asList(array1));
		Set<Object> uniqueElements2 = new HashSet<>(Arrays.asList(array2));
		
		// if size is different, means there will be a mismatch
		if (uniqueElements1.size() != uniqueElements2.size()) return false;
		
		for (Object obj : uniqueElements1) {
			// element not present in both?
			if (!uniqueElements2.contains(obj)) return false;
		}
		
		return true;
	}

}

Output

true false

你怎么在Java中计算整数数组中所有元素的和?

你可以使用一个for循环来遍历数组元素并将它们相加,最后得到总和。

int[] array = { 1, 2, 3, 4, 5 };

int sum = 0;

for (int i : array)
	sum += i;

System.out.println(sum);

19. 在Java中,如何找到数组中第二大的数?

解决这个问题有很多方法。您可以将数组按自然升序排序并取倒数第二个值。然而,排序是一项昂贵的操作。您也可以使用两个变量在单次迭代中找到第二大的值,如下面的示例所示。

private static int findSecondHighest(int[] array) {
	int highest = Integer.MIN_VALUE;
	int secondHighest = Integer.MIN_VALUE;

	for (int i : array) {
		if (i > highest) {
			secondHighest = highest;
			highest = i;
		} else if (i > secondHighest) {
			secondHighest = i;
		}

	}
	return secondHighest;
}

在Java中如何对数组进行洗牌?

下面的示例代码展示了如何使用Random类生成随机索引号并对元素进行洗牌。

int[] array = { 1, 2, 3, 4, 5, 6, 7 };

Random rand = new Random();

for (int i = 0; i < array.length; i++) {
	int randomIndexToSwap = rand.nextInt(array.length);
	int temp = array[randomIndexToSwap];
	array[randomIndexToSwap] = array[i];
	array[i] = temp;
}

System.out.println(Arrays.toString(array));

你可以在另一个for循环内运行洗牌代码,以进行多轮洗牌。

21. 在Java中,你如何找到文本文件中的字符串?

以下示例代码展示了如何使用Scanner类逐行读取文件内容,然后使用String的contains()方法来检查字符串是否存在于文件中。

boolean findStringInFile(String filePath, String str) throws FileNotFoundException {
	File file = new File(filePath);

	Scanner scanner = new Scanner(file);

	// read the file line by line
	while (scanner.hasNextLine()) {
		String line = scanner.nextLine();
		if (line.contains(str)) {
			scanner.close();
			return true;
		}
	}
	scanner.close();

	return false;
}

请注意,示例代码假设要在文件中搜索的字符串不包含换行符。

在Java中,你如何以特定的格式打印日期?

下面的示例代码展示了如何使用SimpleDateFormat类来格式化日期字符串。

String pattern = "MM-dd-yyyy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

String date = simpleDateFormat.format(new Date());
System.out.println(date); // 06-23-2020

了解更多关于Java的SimpleDateFormat。

23. 在Java中如何合并两个列表?

下面的示例代码展示了如何在Java中使用addAll()方法将多个列表合并。

List<String> list1 = new ArrayList<>();
list1.add("1");
List<String> list2 = new ArrayList<>();
list2.add("2");

List<String> mergedList = new ArrayList<>(list1);
mergedList.addAll(list2);
System.out.println(mergedList); // [1, 2]

编写一个Java程序,根据值对HashMap进行排序。

HashMap不是一个有序的集合。下面的示例代码展示了如何根据值对条目进行排序并将它们存储到LinkedHashMap中,该数据结构保持插入的顺序。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class SortHashMapByValue {

	public static void main(String[] args) {
		Map<String, Integer> scores = new HashMap<>();

		scores.put("David", 95);
		scores.put("Jane", 80);
		scores.put("Mary", 97);
		scores.put("Lisa", 78);
		scores.put("Dino", 65);

		System.out.println(scores);

		scores = sortByValue(scores);

		System.out.println(scores);
	}

	private static Map<String, Integer> sortByValue(Map<String, Integer> scores) {
		Map<String, Integer> sortedByValue = new LinkedHashMap<>();

		// get the entry set
		Set<Entry<String, Integer>> entrySet = scores.entrySet();
		System.out.println(entrySet);

		// create a list since the set is unordered
		List<Entry<String, Integer>> entryList = new ArrayList<>(entrySet);
		System.out.println(entryList);

		// sort the list by value
		entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));
		System.out.println(entryList);

		// populate the new hash map
		for (Entry<String, Integer> e : entryList)
			sortedByValue.put(e.getKey(), e.getValue());

		return sortedByValue;
	}

}

25. 在Java中,如何从输入的字符串中移除所有给定字符的出现?

String类没有删除字符的方法。以下示例代码展示了如何使用replace()方法创建一个不含有指定字符的新字符串:

String str1 = "abcdABCDabcdABCD";
		
str1 = str1.replace("a", ""); 

System.out.println(str1); // bcdABCDbcdABCD

在Java中,String是不可变的。所有的字符串操作方法都会返回一个新的字符串,所以你需要将其赋值给另一个变量。了解更多关于在Java中从字符串中删除字符的方法。

在Java中,怎样获取字符串中不同字符及其数量?

你可以从字符串中创建字符数组。然后遍历字符数组,并根据字符创建一个HashMap,其中字符作为键,其出现次数作为值。以下示例代码展示了如何提取字符串中的字符并计数:

String str1 = "abcdABCDabcd";

char[] chars = str1.toCharArray();

Map<Character, Integer> charsCount = new HashMap<>();

for (char c : chars) {
	if (charsCount.containsKey(c)) {
		charsCount.put(c, charsCount.get(c) + 1);
	} else
		charsCount.put(c, 1);
}

System.out.println(charsCount); // {a=2, A=1, b=2, B=1, c=2, C=1, d=2, D=1}

27. 你能通过程序来证明Java中的String对象是不可变的吗?

下面的示例代码展示了如何证明一个String对象是不可变的,代码中的注释解释了每个步骤的含义。

String s1 = "Java"; // "Java" String created in pool and reference assigned to s1

String s2 = s1; //s2 also has the same reference to "Java" in the pool

System.out.println(s1 == s2); // proof that s1 and s2 have the same reference

s1 = "Python"; 
//s1 value got changed above, so how String is immutable?

//in the above case a new String "Python" got created in the pool
//s1 is now referring to the new String in the pool 
//BUT, the original String "Java" is still unchanged and remains in the pool
//s2 is still referring to the original String "Java" in the pool

// proof that s1 and s2 have different reference
System.out.println(s1 == s2); 

System.out.println(s2); 
// prints "Java" supporting the fact that original String value is unchanged, hence String is immutable

你可以写一些Java代码来展示继承吗?

以下示例代码展示了如何使用 extends 关键字创建 Animal 类的子类。新建的 Cat 类继承了 Animal 类的变量,并添加了一些仅属于 Cat 类的代码。

class Animal {
	String color;
}

class Cat extends Animal {
	void meow() {
		System.out.println("Meow");
	}
}

你如何在Java中展示多重继承的菱形问题?

钻石问题发生在一个类从多个类继承,并且当不清楚要执行来自哪个类的方法时,会产生歧义。为了避免钻石问题,在Java中不允许多重继承,以下示例说明了这个问题。

interface I {
	void foo();
}
class A implements I {
	public void foo() {}
}

class B implements I {
	public void foo() {}
}

class C extends A, B { // won't compile
	public void bar() {
		super.foo();
	}
}

你如何在Java中说明一个try catch的例子?

以下示例代码展示了try-catch的例子。

try {
	FileInputStream fis = new FileInputStream("test.txt");
} catch(FileNotFoundException e) {
	e.printStackTrace();
}

从 Java 7 开始,你还可以在一个 catch 块中捕获多个异常,如下例所示。当你在所有的 catch 块中有相同的代码时,这将非常有用。

public static void foo(int x) throws IllegalArgumentException, NullPointerException {
	// some code
}

public static void main(String[] args) {
	try {
		foo(10);
	} catch (IllegalArgumentException | NullPointerException e) {
		System.out.println(e.getMessage());
	}
}

写一个Java程序来展示一个空指针异常。

如果您在空(null)上调用函数,它会引发空指针异常,就像下面的示例代码所示。

public static void main(String[] args) {
	printString(null, 3);
	
}

static void printString(String s, int count) {
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase()); // Exception in thread "main" java.lang.NullPointerException
	}
}

在早期验证中,你应该进行空值检查,就像下面这个示例代码中所示。

static void printString(String s, int count) {
	if (s == null) return;
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase());
	}
}

根据项目要求,您还可以根据参数抛出IllegalArgumentException。

你如何在Java中创建记录?

在Java 16中,记录(Records)被添加为标准功能。使用记录可以仅需少量代码创建一个POJO类。记录会自动生成hashCode()、equals()、getter方法和toString()方法的代码。记录是final的,并且会隐式继承java.lang.Record类。以下示例代码展示了一种创建记录的方法:

import java.util.Map;
 
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}

了解有关Java中的记录的更多信息。有关POJO的详细信息,请参阅维基百科上的Plain old Java 对象。

在Java中如何创建文本块?

Java 15增加了文本块功能。您可以使用文本块创建多行字符串。多行字符串必须写在一对三双引号内,如以下示例所示:

String textBlock = """
		Hi
		Hello
		Yes""";

与创建字符相同,例如Hi\\nHello\\nYes。

请在Java中展示使用开关表达式和多标签(case)语句的示例。

在Java 14中,开关表达式被添加为标准功能。以下示例展示了开关表达式以及多标签case语句。

int choice = 2;

int x = switch (choice) {
    case 1, 2, 3:
	    yield choice;
    default:
	    yield -1;
};

System.out.println("x = " + x); // x = 2

你也可以在switch表达式中使用lambda表达式。

String day = "TH";
String result = switch (day) {
    case "M", "W", "F" -> "MWF";
    case "T", "TH", "S" -> "TTS";

    default -> {
	    if (day.isEmpty())
		    yield "Please insert a valid day.";
	    else
		    yield "Looks like a Sunday.";
    }
};

System.out.println(result); // TTH

35. 从命令行中如何编译和运行Java类?

这个例子指的是下面的Java文件:

public class Test {

public static void main(String args[]) {
		System.out.println("Hi");
	}

}

您可以在终端中使用以下命令进行编译。


  1. javac Test.java

要运行这个类,请在你的终端中使用以下命令:


  1. java Test

最近的版本中,如果类文件不存在,Java命令也会编译程序。如果类在一个包中,比如com.example,那么它应该在com/example文件夹中。编译和运行的命令是:


  1. java com/example/Test.java

如果你的课程需要一些额外的JAR文件来编译和运行,你可以使用java -cp选项。例如:


  1. java -cp .:~/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar com/example/Test.java

在Java中,你如何创建一个枚举?

以下示例代码展示了如何创建一个基本的枚举类型:

public enum ThreadStates {
	START,
	RUNNING,
	WAITING,
	DEAD;
}

ThreadStates是一个枚举,其中包含固定的常量字段START、RUNNING、WAITING和DEAD。所有枚举都隐式地扩展了java.lang.Enum类,并实现了Serializable和Comparable接口。枚举也可以有方法。了解更多关于Java中的枚举的知识。

37. 如何在 Java 中使用forEach()方法?

The forEach() 方法为迭代对象的所有元素提供了一个快捷方式来执行操作。下面的示例代码演示了如何遍历列表元素并打印它们。

List<String> list = new ArrayList<>();

Iterator<String> it = list.iterator();

while (it.hasNext()) {
	System.out.println(it.next());
}

你可以使用lambda表达式在forEach()方法中来缩小代码的大小,如下面的示例代码所示。

List<String> list = new ArrayList<>();

list.forEach(System.out::print);

如何编写具有默认和静态方法的接口?

Java 8在接口中引入了默认方法和静态方法,这样填补了接口和抽象类之间的差距。以下示例代码展示了一种使用默认方法和静态方法编写接口的方式。

public interface Interface1 {
	
	// regular abstract method
	void method1(String str);
	
	default void log(String str) {
		System.out.println("I1 logging::" + str);
	}
	
	static boolean isNull(String str) {
		System.out.println("Interface Null Check");

		return str == null ? true : "".equals(str) ? true : false;
	}

}

在Java 8的接口更改中,深入了解接口中的默认方法和静态方法。

39. 你如何创建一个功能性接口?

一个只有一个抽象方法的接口被称为函数式接口。函数式接口的主要优势是可以使用lambda表达式来实例化它们,避免使用臃肿的匿名类实现。@FunctionalInterface注解表示一个函数式接口,如下面的示例代码所示:

@FunctionalInterface
interface Foo {
	void test();
}

请展示一个在Java中使用lambda表达式的例子。

Runnable是函数式接口的一个很好的例子。您可以使用lambda表达式来创建一个可运行的实例,如下面的示例代码所示:

Runnable r1 = () -> System.out.println("My Runnable");

给出Java中重载和重写的示例。

当一个类有两个或更多的方法拥有相同的名称时,它们被称为重载方法。下面的示例代码展示了一个被称为print的重载方法。

class Foo {
	void print(String s) {
		System.out.println(s);
	}

	void print(String s, int count) {
		while (count > 0) {
			System.out.println(s);
			count--;
		}
	}

}

当在子类中实现了超类方法时,这被称为覆盖。以下示例代码展示了如何对在两个类中实现的printname()方法进行注释。

class Base {
	void printName() {
		System.out.println("Base Class");
	}
}

class Child extends Base {
	@Override
	void printName() {
		System.out.println("Child Class");
	}
}

了解Java中的覆盖(overriding)和重载(overloading)。

42. Can you predict what will be produced?
43. What do you think will be the outcome?
44. Can you guess the resulting output?
45. What do you expect the output to be?
46. Can you anticipate the output that will be generated?
47. What do you suppose will be the produced result?
48. Can you hypothesize the output that will be produced?
49. What do you anticipate the resulting output will be?

通过猜测以下代码片段的输出来测试你自己的能力。


String s1 = "abc";
String s2 = "abc";

System.out.println("s1 == s2 is:" + s1 == s2);
输出
错误给定语句的输出是错误的,因为+运算符的优先级高于==运算符。所以给定的表达式被计算为“s1 == s2是:abc” == “abc”,这是错误的。


String s3 = "JournalDev";
int start = 1;
char end = 5;

System.out.println(s3.substring(start, end));
输出
ourn给定语句的输出是ourn。首字符自动转换为整数。然后,由于首字符索引为0,它会从o开始打印直到n。请注意,String的子字符串方法创建一个从start索引开始并延伸到end-1索引处的子字符串。


HashSet shortSet = new HashSet();

	for (short i = 0; i < 100; i++) {
    shortSet.add(i);
    shortSet.remove(i - 1);
}

System.out.println(shortSet.size());
输出
100shortSet的大小为100。Java中的自动装箱功能意味着具有原始类型short的表达式i将被转换为Short对象。同样,具有原始类型int的表达式i – 1将被自动装箱为一个Integer对象。由于HashSet中没有Integer对象,所以没有任何东西被移除,大小仍然是100。


try {
	if (flag) {
  		while (true) {
   		}
   	} else {
   		System.exit(1);
   	}
} finally {
   	System.out.println("In Finally");
}
输出
没有输出。如果标志位为真,这段代码会导致一个无限循环;如果标志位为假,程序会退出。最终块将永远不会执行。

String str = null;
String str1="abc";

System.out.println(str1.equals("abc") | str.equals(null));
输出
主线程中的异常:java.lang.NullPointerException:无法调用”String.equals(Object)”,因为””为空给定的打印语句将会抛出java.lang.NullPointerException异常,因为逻辑或运算符在返回结果之前会评估两个文字。由于str为空,.equals()方法将抛出异常。总是建议使用短路逻辑运算符,如||和&&,它们会从左到右评估文字值。在这种情况下,由于第一个文字将返回true,它将跳过对第二个文字的评估。


String x = "abc";
String y = "abc";

x.concat(y);

System.out.print(x);
输出
abcx.concat(y)创建了一个新字符串,但未被赋值给x,所以x的值没有改变。


public class MathTest {

 	public void main(String[] args) {  		
   		int x = 10 * 10 - 10;
   		
   		System.out.println(x);
   	}
   
}
错误:类MathTest中的主方法不是静态的,请将主方法定义为:
public static void main(String[] args)尽管看起来这个问题似乎涉及数学运算符的执行顺序,但问题实际上在于注意到主方法没有被声明为静态的。


public class Test {
   
  	public static void main(String[] args) {
   		try {
   			throw new IOException("Hello");
   		} catch(IOException | Exception e) {
   			System.out.println(e.getMessage());
   		}
   	}
}
这段代码在编译时出现错误。IOException异常已经被替代的Exception捕获。

找出以下代码片段中的5个错误。

Note: Chinese translations may vary depending on the context and specific technical terms used in the code snippet.

package com.digitalocean.programming-interviews;

public class String Programs {

	static void main(String[10] args) {
		String s = "abc"
		System.out.println(s);
	}
}
答案包名不能有连字符。
类名不能有空格。
main方法不是public,所以无法运行。
main方法的参数不应该指定大小。
字符串定义中缺少分号。

结论

这个收集了50个Java编程面试题的合集,涵盖了从初学者到专家级别的问题,以帮助你为面试做好准备。

推荐阅读:

  • Java Tricky Interview Questions
  • Java String Interview Questions