IntelliJ IDEA Guide — Setup, Shortcuts, Plugins, Refactoring, Debugging, Profiling
IntelliJ IDEA is the most powerful IDE for Java and JVM languages, with deep code analysis, intelligent refactoring, and extensive plugin ecosystem. This guide covers everything from initial setup to advanced debugging and profiling.
What You’ll Learn
You’ll set up IntelliJ IDEA for maximum productivity, master essential keyboard shortcuts, discover must-have plugins, refactor code safely and efficiently, debug complex applications, and profile JVM performance with async-profiler. At DodaTech, Durga Antivirus Pro uses IntelliJ IDEA for its Java-based scanning engine development.
Why IntelliJ IDEA Matters
IntelliJ IDEA’s deep static analysis catches errors before you run the code. Its refactoring tools transform codebases safely in seconds. The integrated debugger and profiler eliminate the need for separate tools. For Java and Kotlin development, IntelliJ IDEA is the industry standard.
Learning Path
flowchart LR
A[VS Code Basics] --> B[IntelliJ IDEA<br/>You are here]
B --> C[Advanced Debugging]
C --> D[IDE Shortcuts]
style B fill:#f90,color:#fff
Initial Setup
Download and Install
# Download IntelliJ IDEA (Ultimate or Community)
wget https://download.jetbrains.com/idea/ideaIU-2024.2.tar.gz
# Extract and run
tar xzf ideaIU-2024.2.tar.gz
cd idea-IU-242.*/bin
./idea.shProject Configuration
# Create a new Java project
# File → New → Project → Java
# Choose JDK (File → Project Structure → SDK)
# Project SDK settings
# File → Project Structure (Ctrl+Alt+Shift+S)
# Project SDK: 21 (LTS)
# Language level: 21 (Preview)Essential Keyboard Shortcuts
Navigation
| Shortcut | Action |
|---|---|
Ctrl+N | Find class |
Ctrl+Shift+N | Find file |
Ctrl+Alt+Shift+N | Find symbol |
Ctrl+E | Recent files |
Ctrl+Shift+E | Recently changed files |
Ctrl+B | Go to declaration |
Ctrl+Alt+B | Go to implementation |
Ctrl+U | Go to super |
Ctrl+F12 | File structure |
Alt+F7 | Find usages |
Ctrl+Shift+F7 | Highlight usages in file |
Ctrl+Alt+F7 | Show usages |
Editing
| Shortcut | Action |
|---|---|
Ctrl+D | Duplicate line |
Ctrl+Y | Delete line |
Ctrl+Shift+Up/Down | Move line |
Alt+Shift+Up/Down | Move statement |
Ctrl+Shift+Enter | Complete statement |
Ctrl+J | Insert live template |
Ctrl+Alt+T | Surround with (try/catch, if, etc.) |
Ctrl+Shift+U | Toggle case |
Ctrl+Alt+L | Format code |
Ctrl+Alt+O | Optimize imports |
Refactoring
| Shortcut | Action |
|---|---|
Shift+F6 | Rename |
Ctrl+F6 | Change signature |
Ctrl+Alt+V | Extract variable |
Ctrl+Alt+C | Extract constant |
Ctrl+Alt+F | Extract field |
Ctrl+Alt+M | Extract method |
Ctrl+Alt+P | Extract parameter |
Ctrl+Alt+N | Inline |
F6 | Move |
F5 | Copy |
Must-Have Plugins
# Install via Settings → Plugins (Ctrl+Alt+S)
# Essential plugins:
# 1. SonarLint — Real-time code quality checks
# 2. GitToolBox — Git status in editor, blame annotations
# 3. Key Promoter X — Shows shortcut for any action you click
# 4. Rainbow Brackets — Color-coded brackets
# 5. .env files — Environment file support
# 6. Spring Assistant — Spring Boot configuration completion
# 7. MyBatisX — MyBatis mapper navigation
# 8. Async Profiler — Built-in JVM profilingRefactoring Techniques
IntelliJ’s refactoring engine analyzes your entire codebase to ensure transformations are safe:
// Before — hardcoded value
public class OrderService {
private static final double TAX_RATE = 0.08;
public double calculateTotal(double subtotal) {
return subtotal + (subtotal * TAX_RATE);
}
}
// Extract parameter refactoring (Ctrl+Alt+P)
public class OrderService {
public double calculateTotal(double subtotal, double taxRate) {
return subtotal + (subtotal * taxRate);
}
}
// Rename refactoring (Shift+F6) — updates all references automatically
public class OrderService {
public double calculateTotalWithTax(double subtotal, double taxRate) {
return subtotal + (subtotal * taxRate);
}
}Safe Rename (Shift+F6)
Renames variables, methods, classes, and files while updating all references:
// Before
public void process() {
List<Order> o = orderRepo.findAll();
for (Order order : o) {
// ...
}
}
// After Shift+F6 on 'o' → rename to 'orders'
public void process() {
List<Order> orders = orderRepo.findAll();
for (Order order : orders) {
// ...
}
}Extract Method (Ctrl+Alt+M)
Select code and extract it into a new method with proper parameters:
// Before — select the loop body, press Ctrl+Alt+M
public void processOrders(List<Order> orders) {
for (Order order : orders) {
if (order.getStatus() == OrderStatus.PENDING) {
try {
paymentService.process(order);
order.setStatus(OrderStatus.PAID);
notificationService.sendConfirmation(order);
} catch (PaymentException e) {
log.error("Payment failed for order {}", order.getId(), e);
order.setStatus(OrderStatus.FAILED);
}
}
}
}
// After extraction — new method with clear name
public void processOrders(List<Order> orders) {
for (Order order : orders) {
processSingleOrder(order);
}
}
private void processSingleOrder(Order order) {
if (order.getStatus() == OrderStatus.PENDING) {
try {
paymentService.process(order);
order.setStatus(OrderStatus.PAID);
notificationService.sendConfirmation(order);
} catch (PaymentException e) {
log.error("Payment failed for order {}", order.getId(), e);
order.setStatus(OrderStatus.FAILED);
}
}
}Debugging
Conditional Breakpoints
for (int i = 0; i < 10000; i++) {
// Right-click breakpoint → set condition: i == 5678
processItem(items[i]);
}Right-click a breakpoint dot to set conditions, pass count, or enable logging:
| Feature | Use |
|---|---|
| Condition | Break only when expression is true |
| Pass count | Break after N hits |
| Log message | Print to console without stopping |
| Remove once hit | One-shot breakpoint |
| Disabled until hitting another | Breakpoint chaining |
Evaluate Expression (Alt+F8)
Inspect or modify any expression while paused:
// At breakpoint, press Alt+F8 and type:
order.getTotal() > 1000
// Returns: true
// Modify a variable:
order.setStatus(OrderStatus.REFUNDED)Frame Drop
Select a method call in the stack trace and drop to re-execute it. Useful for testing different code paths without restarting.
JVM Profiling
Async Profiler (built into IntelliJ Ultimate) profiles CPU, memory, and allocations:
// Profile CPU — find hot methods
// Run → Profile → CPU Sample
// Profile allocations — find allocation hotspots
// Run → Profile → Allocation SamplingAnalyzing a CPU Profile
// Example: Identify the slow method
public class ReportGenerator {
// This method shows 80% CPU usage in profile
public byte[] generatePdfReport(List<Transaction> transactions) {
// Each PDF page regenerates styles — expensive
for (Transaction t : transactions) {
PdfPage page = new PdfPage();
// ...
}
}
// After optimization — reuse styles
public byte[] generatePdfReportOptimized(List<Transaction> transactions) {
PdfStyle style = new PdfStyle(); // Created once
for (Transaction t : transactions) {
PdfPage page = new PdfPage(style); // Reuse style
// ...
}
}
}Common IntelliJ Mistakes
1. Not Using Local History
Deleted a file or made changes you regret? Right-click → Local History → Show History. IntelliJ saves local revisions even without Git.
2. Ignoring Inspections
Yellow and red underlines aren’t noise. IntelliJ’s inspections catch null pointer issues, unused code, potential bugs, and performance problems. Press Alt+Enter on any warning.
3. Manual Refactoring
Never search-and-replace for variable/method names. Use Shift+F6 (Rename) which updates all references and handles name clashes.
4. Not Configuring Live Templates
Live templates (File → Settings → Live Templates) generate common code patterns. Create templates for log statements, getter/setter patterns, test setups, and error handling blocks.
5. Debugging Without Breakpoint Conditions
Looping 100000 times and manually clicking Resume? Set a breakpoint condition: right-click the breakpoint → enter i == 99999.
6. Overlooking Structural Search
Edit → Find → Search Structurally finds code patterns based on structure, not text. Find all try-with-resources blocks, lambda expressions, or method signatures matching a pattern.
7. Not Using the Terminal Tool Window
Alt+F12 opens the embedded terminal. Run Maven/Gradle commands, Git operations, and server startup without leaving the IDE.
Practice Questions
1. What shortcut finds a class by name?
Ctrl+N (or Cmd+N on macOS). Type the class name (camel case abbreviations work: NPE → NullPointerException).
2. How do you rename a method and update all references?
Shift+F6. IntelliJ finds all usages, renames the method, and updates every call site. It even handles overridden methods and method references.
3. What is the difference between Extract Method and Inline? Extract Method (Ctrl+Alt+M) turns selected code into a new method. Inline (Ctrl+Alt+N) replaces a method call with its body. They’re inverse operations.
4. How do you set a conditional breakpoint?
Right-click the breakpoint dot in the gutter. Set a condition like response.getStatus() == 500 — execution only pauses when the condition is true.
5. Challenge: You have a 10,000-line class that handles payment processing, notification, and reporting. Use IntelliJ’s refactoring tools to split it into three focused classes. Which refactoring operations would you use? Answer: Extract Method for distinct operations, then Extract Class (or Move Members) to move related methods into new classes. Use Move (F6) to relocate classes to appropriate packages.
Mini Project: Refactor a Legacy Class
Apply IntelliJ’s refactoring tools to improve this class:
// LegacyOrderProcessor.java — Before refactoring
public class LegacyOrderProcessor {
public void handle(Order o) throws Exception {
// Validate
if (o.getItems().isEmpty()) throw new Exception("No items");
if (o.getTotal() <= 0) throw new Exception("Invalid total");
// Process payment
String chargeId = chargeCreditCard(o.getCardNumber(), o.getTotal());
o.setChargeId(chargeId);
// Send emails
sendEmail(o.getCustomerEmail(), "Order Confirmed",
"Your order #" + o.getId() + " has been confirmed.");
// Update inventory
for (Item item : o.getItems()) {
item.setQuantity(item.getQuantity() - 1);
inventoryRepo.save(item);
}
// Generate receipt
String receipt = "Order #" + o.getId() + "\n";
for (Item item : o.getItems()) {
receipt += item.getName() + ": $" + item.getPrice() + "\n";
}
receipt += "Total: $" + o.getTotal();
saveReceipt(o.getId(), receipt);
}
private String chargeCreditCard(String card, double amount) { return "ch_" + System.currentTimeMillis(); }
private void sendEmail(String to, String subject, String body) { /* email logic */ }
private void saveReceipt(long orderId, String receipt) { /* save logic */ }
}Apply these refactorings:
- Extract separate methods for validation, payment, notification, inventory, receipt
- Move payment logic to
PaymentService - Move notification logic to
NotificationService - Move receipt generation to
ReceiptService - Rename
handletoprocessOrder - Replace
Exceptionwith specific custom exceptions
FAQ
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-20.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro